fscr 6.2.3 → 7.3.0

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 (98) hide show
  1. package/README.md +48 -30
  2. package/dist/index.js +502 -185
  3. package/dist/lib/auth/auth-conf.js +49 -45
  4. package/dist/lib/cache/README.md +341 -0
  5. package/dist/lib/cache/cli.js +152 -0
  6. package/dist/lib/cache/file-watcher.js +193 -0
  7. package/dist/lib/cache/index.js +422 -0
  8. package/dist/lib/cache/monitor.js +224 -0
  9. package/dist/lib/commands/doctor.js +225 -0
  10. package/dist/lib/completions/completion.js +342 -0
  11. package/dist/lib/completions/generator.js +152 -0
  12. package/dist/lib/completions/scripts/bash.sh +108 -0
  13. package/dist/lib/completions/scripts/fish.sh +105 -0
  14. package/dist/lib/completions/scripts/powershell.ps1 +168 -0
  15. package/dist/lib/completions/scripts/zsh.sh +124 -0
  16. package/dist/lib/diagnostics/cache.js +121 -0
  17. package/dist/lib/diagnostics/fileSystem.js +236 -0
  18. package/dist/lib/diagnostics/gitCheck.js +41 -0
  19. package/dist/lib/diagnostics/nodeVersion.js +68 -0
  20. package/dist/lib/diagnostics/packageManager.js +64 -0
  21. package/dist/lib/diagnostics/performance.js +141 -0
  22. package/dist/lib/encryption/decryptConfig.js +3 -2
  23. package/dist/lib/encryption/encryption.js +153 -113
  24. package/dist/lib/generators/generateFScripts.js +16 -13
  25. package/dist/lib/generators/generateToc.js +23 -14
  26. package/dist/lib/generators/index.js +1 -1
  27. package/dist/lib/git/pub.js +27 -31
  28. package/dist/lib/git/taskRunner.js +79 -69
  29. package/dist/lib/git/validateNotDev.js +65 -54
  30. package/dist/lib/optionList.js +69 -57
  31. package/dist/lib/parsers/parseScriptsMd.cached.js +208 -0
  32. package/dist/lib/parsers/parseScriptsMd.js +88 -79
  33. package/dist/lib/parsers/parseScriptsPackage.js +4 -3
  34. package/dist/lib/performance/cache.js +199 -0
  35. package/dist/lib/performance/lazy-loader.js +189 -0
  36. package/dist/lib/performance/monitor.js +303 -0
  37. package/dist/lib/plugins/deployment/index.js +113 -0
  38. package/dist/lib/plugins/hooks.js +17 -0
  39. package/dist/lib/plugins/loader.js +91 -0
  40. package/dist/lib/plugins/task-notifier/index.js +72 -0
  41. package/dist/lib/release/bump.js +51 -43
  42. package/dist/lib/release/commitWithMessage.js +80 -52
  43. package/dist/lib/release/publish.js +19 -14
  44. package/dist/lib/release/pushToGit.js +40 -31
  45. package/dist/lib/release/releasenotes.js +116 -97
  46. package/dist/lib/release/seeChangedFiles.js +68 -60
  47. package/dist/lib/release/sort.js +200 -116
  48. package/dist/lib/release/tree.js +161 -147
  49. package/dist/lib/release/validateNotDev.js +52 -44
  50. package/dist/lib/running/index.js +1 -1
  51. package/dist/lib/running/runCLICommand.js +41 -31
  52. package/dist/lib/running/runParallel.js +61 -59
  53. package/dist/lib/running/runSequence.js +55 -53
  54. package/dist/lib/startScripts.js +129 -114
  55. package/dist/lib/taskList.js +99 -84
  56. package/dist/lib/test-files/.fscripts.md +113 -0
  57. package/dist/lib/test-files/.fscripts.test.md +103 -0
  58. package/dist/lib/test-files/.fscriptsb.md +107 -0
  59. package/dist/lib/test-files/.mdtest.md +40 -0
  60. package/dist/lib/test-files/consoleSample.js +17 -0
  61. package/dist/lib/test-files/inputSample.js +20 -0
  62. package/dist/lib/test-files/testConsole.js +1 -0
  63. package/dist/lib/test-files/testInput.js +2 -0
  64. package/dist/lib/upgradePackages.js +56 -46
  65. package/dist/lib/utils/clear.js +16 -13
  66. package/dist/lib/utils/console.js +27 -21
  67. package/dist/lib/utils/encryption.js +55 -13
  68. package/dist/lib/utils/hash.js +128 -0
  69. package/dist/lib/utils/helpers.js +153 -142
  70. package/dist/lib/utils/index.js +1 -1
  71. package/dist/lib/utils/prompt.js +24 -29
  72. package/package.json +20 -32
  73. package/dist/lib/codemod/arrow.js +0 -13
  74. package/dist/lib/codemod/arrow2.js +0 -67
  75. package/dist/lib/codemod/funcs.js +0 -25
  76. package/dist/lib/codemod/removeConsole.js +0 -12
  77. package/dist/lib/codemod/test.js +0 -8
  78. package/dist/lib/components/App.js +0 -64
  79. package/dist/lib/components/Selector.js +0 -133
  80. package/dist/lib/components/TabChanger.js +0 -113
  81. package/dist/lib/components/Table.js +0 -177
  82. package/dist/lib/components/Tabs.js +0 -221
  83. package/dist/lib/generateFScripts.js +0 -25
  84. package/dist/lib/generateToc.js +0 -30
  85. package/dist/lib/helpers.js +0 -191
  86. package/dist/lib/parseScriptsMd.js +0 -85
  87. package/dist/lib/parseScriptsPackage.js +0 -9
  88. package/dist/lib/release/index.js +0 -4
  89. package/dist/lib/run/lib.js +0 -454
  90. package/dist/lib/run/main-p.js +0 -59
  91. package/dist/lib/run/main-s.js +0 -56
  92. package/dist/lib/run/parse-cli-args.js +0 -222
  93. package/dist/lib/run/run-p.js +0 -30
  94. package/dist/lib/run/run-s.js +0 -57
  95. package/dist/lib/runCLICommand.js +0 -30
  96. package/dist/lib/runParallel.js +0 -20
  97. package/dist/lib/runSequence.js +0 -38
  98. package/dist/lib/taskListAutoComplete.js +0 -15
@@ -10,54 +10,58 @@ import { readJson } from "../utils/helpers.js";
10
10
  const scriptsDir = process.cwd();
11
11
  const rootDir = path.join(scriptsDir, "./");
12
12
  const packagePath = path.join(rootDir, "package.json");
13
+
13
14
  const serverConfig = async () => {
14
- let index = await fs.readFileSync(path.resolve(__dirname, "./index.html"), "utf-8");
15
- return new Promise(resolve => {
16
- const server = http.createServer(async (req, res) => {
17
- res.setHeader("Access-Control-Allow-Origin", "*");
18
- res.setHeader("Access-Control-Request-Method", "*");
19
- res.setHeader("Access-Control-Allow-Methods", "OPTIONS, GET, POST");
20
- res.setHeader("Access-Control-Allow-Headers", "*");
21
- const headers = {
22
- "Access-Control-Allow-Origin": "*",
23
- "Content-Type": "text/json",
24
- "Access-Control-Allow-Methods": "OPTIONS, POST, GET",
25
- "Access-Control-Max-Age": 2592000 // 30 days
26
- };
27
- if (req.method === "POST") {
28
- res.writeHead(200, headers);
29
- let body = "";
30
- req.on("data", chunk => {
31
- body += chunk.toString(); // convert Buffer to string
32
- });
33
- req.on("end", () => {
34
- res.end(JSON.stringify({
35
- done: true
36
- }));
37
- server.destroy();
38
- resolve(JSON.parse(body));
39
- });
40
- } else {
41
- res.end(index);
42
- }
43
- }).listen(5252, () => {
44
- // open the browser to the authorize url to start the workflow
45
- open("http://localhost:5252", {
46
- wait: false
47
- }).then(cp => cp.unref());
15
+ let index = await fs.readFileSync(path.resolve(__dirname, "./index.html"), "utf-8");
16
+
17
+ return new Promise((resolve) => {
18
+ const server = http
19
+ .createServer(async (req, res) => {
20
+ res.setHeader("Access-Control-Allow-Origin", "*");
21
+ res.setHeader("Access-Control-Request-Method", "*");
22
+ res.setHeader("Access-Control-Allow-Methods", "OPTIONS, GET, POST");
23
+ res.setHeader("Access-Control-Allow-Headers", "*");
24
+
25
+ const headers = {
26
+ "Access-Control-Allow-Origin": "*",
27
+ "Content-Type": "text/json",
28
+ "Access-Control-Allow-Methods": "OPTIONS, POST, GET",
29
+ "Access-Control-Max-Age": 2592000 // 30 days
30
+ };
31
+ if (req.method === "POST") {
32
+ res.writeHead(200, headers);
33
+
34
+ let body = "";
35
+ req.on("data", (chunk) => {
36
+ body += chunk.toString(); // convert Buffer to string
37
+ });
38
+ req.on("end", () => {
39
+ res.end(JSON.stringify({ done: true }));
40
+ server.destroy();
41
+ resolve(JSON.parse(body));
42
+ });
43
+ } else {
44
+ res.end(index);
45
+ }
46
+ })
47
+ .listen(5252, () => {
48
+ // open the browser to the authorize url to start the workflow
49
+ open("http://localhost:5252", { wait: false }).then((cp) => cp.unref());
50
+ });
51
+ destroyer(server);
48
52
  });
49
- destroyer(server);
50
- });
51
53
  };
54
+
52
55
  async function main() {
53
- const config = await serverConfig();
54
- const packageJson = await readJson(packagePath);
55
- let configFile = path.resolve(rootDir, "config.json");
56
- if (packageJson.fscripts) {
57
- if (packageJson.fscripts.config) {
58
- configFile = path.resolve(rootDir, packageJson.fscripts.config);
56
+ const config = await serverConfig();
57
+ const packageJson = await readJson(packagePath);
58
+ let configFile = path.resolve(rootDir, "config.json");
59
+ if (packageJson.fscripts) {
60
+ if (packageJson.fscripts.config) {
61
+ configFile = path.resolve(rootDir, packageJson.fscripts.config);
62
+ }
59
63
  }
60
- }
61
- await fs.writeFileSync(configFile, JSON.stringify(config, null, 4), "utf-8");
64
+ await fs.writeFileSync(configFile, JSON.stringify(config, null, 4), "utf-8");
62
65
  }
63
- export default main;
66
+
67
+ export default main;
@@ -0,0 +1,341 @@
1
+ # FSCR Cache System
2
+
3
+ Smart caching system with TTL support, automatic invalidation, and performance monitoring for FSCR v7.0.0.
4
+
5
+ ## Features
6
+
7
+ - **In-memory caching** with configurable TTL
8
+ - **File-based invalidation** using modification time tracking
9
+ - **Automatic file watching** for cache invalidation on changes
10
+ - **Performance monitoring** with hit rate tracking
11
+ - **Size management** with LRU eviction
12
+ - **Event system** for cache lifecycle hooks
13
+ - **CLI commands** for cache management
14
+
15
+ ## Quick Start
16
+
17
+ ### Using the Cache
18
+
19
+ The cache is automatically used when parsing scripts:
20
+
21
+ ```javascript
22
+ import parseScriptFile from './lib/parsers/parseScriptsMd.js';
23
+
24
+ // Uses cache by default
25
+ const scripts = await parseScriptFile();
26
+
27
+ // Disable cache for specific call
28
+ const scripts = await parseScriptFile({ useCache: false });
29
+ ```
30
+
31
+ ### CLI Commands
32
+
33
+ ```bash
34
+ # Show cache statistics
35
+ fsr cache stats
36
+
37
+ # Show verbose statistics
38
+ fsr cache stats --verbose
39
+
40
+ # Clear all cache entries
41
+ fsr cache clear
42
+
43
+ # List cached entries
44
+ fsr cache list
45
+
46
+ # List with custom limit
47
+ fsr cache list --limit 20
48
+
49
+ # Run performance benchmark
50
+ fsr cache benchmark
51
+
52
+ # Export statistics to JSON
53
+ fsr cache export --output stats.json
54
+ ```
55
+
56
+ ## Performance Targets
57
+
58
+ | Metric | Target | Typical |
59
+ |--------|--------|---------|
60
+ | Cold cache | ~450ms | 450-500ms |
61
+ | Warm cache | ~45ms | 40-50ms |
62
+ | Speedup | 10x | 10-12x |
63
+ | Hit rate | >80% | 85-95% |
64
+
65
+ ## Architecture
66
+
67
+ ### Core Components
68
+
69
+ 1. **CacheManager** (`lib/cache/index.js`)
70
+ - In-memory cache with TTL support
71
+ - File-based cache key generation
72
+ - Automatic expiration and cleanup
73
+ - Statistics tracking
74
+
75
+ 2. **FileWatcher** (`lib/cache/file-watcher.js`)
76
+ - Monitors files for changes
77
+ - Automatic cache invalidation
78
+ - Debounced event handling
79
+
80
+ 3. **CacheMonitor** (`lib/cache/monitor.js`)
81
+ - Performance metrics collection
82
+ - Statistics display and reporting
83
+ - Hit rate calculation
84
+
85
+ 4. **Hash Utilities** (`lib/utils/hash.js`)
86
+ - Cache key generation
87
+ - File metadata tracking
88
+ - Content hashing
89
+
90
+ ## API Reference
91
+
92
+ ### CacheManager
93
+
94
+ ```javascript
95
+ import { CacheManager, getCache } from './lib/cache/index.js';
96
+
97
+ // Create a new cache instance
98
+ const cache = new CacheManager({
99
+ defaultTTL: 300000, // 5 minutes
100
+ maxSize: 100,
101
+ enableStats: true
102
+ });
103
+
104
+ // Use global singleton
105
+ const cache = getCache();
106
+
107
+ // Set a value
108
+ cache.set('key', data, {
109
+ ttl: 60000, // Optional custom TTL
110
+ filePath: '/path/to/file.txt' // Optional file tracking
111
+ });
112
+
113
+ // Get a value
114
+ const data = cache.get('key'); // Returns null if not found or expired
115
+
116
+ // Invalidate an entry
117
+ cache.invalidate('key');
118
+
119
+ // Invalidate all entries for a file
120
+ cache.invalidateFile('/path/to/file.txt');
121
+
122
+ // Clear all entries
123
+ cache.clear();
124
+
125
+ // Check if valid
126
+ cache.isValid('key');
127
+
128
+ // Get statistics
129
+ const stats = cache.getStats();
130
+ ```
131
+
132
+ ### FileWatcher
133
+
134
+ ```javascript
135
+ import FileWatcher from './lib/cache/file-watcher.js';
136
+ import { getCache } from './lib/cache/index.js';
137
+
138
+ const cache = getCache();
139
+ const watcher = new FileWatcher(cache);
140
+
141
+ // Watch a file
142
+ watcher.watch('/path/to/file.txt');
143
+
144
+ // Unwatch a file
145
+ watcher.unwatch('/path/to/file.txt');
146
+
147
+ // Check if watching
148
+ watcher.isWatching('/path/to/file.txt');
149
+
150
+ // Get statistics
151
+ const stats = watcher.getStats();
152
+
153
+ // Cleanup
154
+ watcher.destroy();
155
+ ```
156
+
157
+ ### CacheMonitor
158
+
159
+ ```javascript
160
+ import CacheMonitor from './lib/cache/monitor.js';
161
+ import { getCache } from './lib/cache/index.js';
162
+
163
+ const cache = getCache();
164
+ const monitor = new CacheMonitor(cache);
165
+
166
+ // Record performance
167
+ monitor.recordColdCache(450); // 450ms
168
+ monitor.recordWarmCache(45); // 45ms
169
+
170
+ // Get statistics
171
+ const stats = monitor.getStats();
172
+
173
+ // Print to console
174
+ monitor.printStats({ verbose: true });
175
+
176
+ // Export as JSON
177
+ const json = monitor.toJSON();
178
+ ```
179
+
180
+ ## Cache Configuration
181
+
182
+ Default configuration:
183
+
184
+ ```javascript
185
+ {
186
+ defaultTTL: 300000, // 5 minutes
187
+ maxSize: 100, // Maximum entries
188
+ enableStats: true // Track statistics
189
+ }
190
+ ```
191
+
192
+ ### Environment Variables
193
+
194
+ ```bash
195
+ # Disable cache globally
196
+ FSCR_CACHE_ENABLED=false
197
+
198
+ # Custom TTL (milliseconds)
199
+ FSCR_CACHE_TTL=600000
200
+
201
+ # Custom max size
202
+ FSCR_CACHE_MAX_SIZE=200
203
+ ```
204
+
205
+ ## Cache Invalidation
206
+
207
+ ### Automatic Invalidation
208
+
209
+ 1. **TTL Expiration**: Entries expire after configured TTL
210
+ 2. **File Changes**: Monitored files trigger invalidation
211
+ 3. **Size Limits**: LRU eviction when cache is full
212
+
213
+ ### Manual Invalidation
214
+
215
+ ```javascript
216
+ import { getCache } from './lib/cache/index.js';
217
+
218
+ const cache = getCache();
219
+
220
+ // Invalidate specific entry
221
+ cache.invalidate('key');
222
+
223
+ // Invalidate by file path
224
+ cache.invalidateFile('/path/to/fscripts.md');
225
+
226
+ // Clear all
227
+ cache.clear();
228
+ ```
229
+
230
+ ## Events
231
+
232
+ The cache emits events for lifecycle hooks:
233
+
234
+ ```javascript
235
+ cache.on('set', ({ key, data, ttl }) => {
236
+ console.log(`Cache set: ${key}`);
237
+ });
238
+
239
+ cache.on('hit', ({ key, data }) => {
240
+ console.log(`Cache hit: ${key}`);
241
+ });
242
+
243
+ cache.on('invalidate', ({ key }) => {
244
+ console.log(`Cache invalidated: ${key}`);
245
+ });
246
+
247
+ cache.on('evict', ({ key }) => {
248
+ console.log(`Cache evicted: ${key}`);
249
+ });
250
+
251
+ cache.on('cleanup', ({ count }) => {
252
+ console.log(`Cleaned ${count} expired entries`);
253
+ });
254
+ ```
255
+
256
+ ## Testing
257
+
258
+ ### Unit Tests
259
+
260
+ ```bash
261
+ # Run all cache tests
262
+ npm test tests/cache.test.js
263
+
264
+ # Run with coverage
265
+ npm test -- --coverage tests/cache.test.js
266
+ ```
267
+
268
+ ### Benchmarks
269
+
270
+ ```bash
271
+ # Run performance benchmarks
272
+ node tests/cache.bench.js
273
+
274
+ # Via CLI
275
+ fsr cache benchmark
276
+ ```
277
+
278
+ ## Memory Usage
279
+
280
+ Typical memory usage per cache entry:
281
+
282
+ - Small entry (task metadata): ~1-2KB
283
+ - Medium entry (parsed script): ~3-5KB
284
+ - Large entry (full fscripts.md): ~10-20KB
285
+
286
+ For 100 cached entries: ~500KB - 2MB
287
+
288
+ ## Troubleshooting
289
+
290
+ ### Cache Not Working
291
+
292
+ 1. Check if cache is enabled:
293
+ ```javascript
294
+ const cache = getCache();
295
+ console.log(cache.size()); // Should be > 0 after use
296
+ ```
297
+
298
+ 2. Verify file watching:
299
+ ```javascript
300
+ const stats = watcher.getStats();
301
+ console.log(stats.filesWatched);
302
+ ```
303
+
304
+ 3. Check hit rate:
305
+ ```bash
306
+ fsr cache stats
307
+ ```
308
+
309
+ ### Low Hit Rate
310
+
311
+ - Increase TTL if files don't change often
312
+ - Check for frequent file modifications
313
+ - Verify cache size is sufficient
314
+
315
+ ### High Memory Usage
316
+
317
+ - Reduce `maxSize` configuration
318
+ - Decrease `defaultTTL` for faster cleanup
319
+ - Monitor with `cache.getStats()`
320
+
321
+ ## Best Practices
322
+
323
+ 1. **Use default settings** for most cases
324
+ 2. **Enable file watching** for automatic invalidation
325
+ 3. **Monitor hit rate** to verify cache effectiveness
326
+ 4. **Clear cache** after bulk file operations
327
+ 5. **Use TTL of 0** for data that rarely changes
328
+ 6. **Benchmark** to verify 10x speedup target
329
+
330
+ ## Future Enhancements
331
+
332
+ - [ ] Persistent cache (Redis/SQLite)
333
+ - [ ] Cache warming on startup
334
+ - [ ] Distributed cache support
335
+ - [ ] Cache compression
336
+ - [ ] Smart preloading based on patterns
337
+ - [ ] Cache metrics dashboard
338
+
339
+ ## License
340
+
341
+ MIT
@@ -0,0 +1,152 @@
1
+ /**
2
+ * Cache CLI commands
3
+ * @module cache/cli
4
+ */
5
+
6
+ import chalk from 'chalk';
7
+ import { getCache, resetCache } from './index.js';
8
+ import CacheMonitor from './monitor.js';
9
+
10
+ /**
11
+ * Show cache statistics
12
+ * @param {Object} options - Options
13
+ * @param {boolean} [options.verbose=false] - Show verbose output
14
+ */
15
+ export async function showCacheStats(options = {}) {
16
+ const cache = getCache();
17
+ const monitor = new CacheMonitor(cache);
18
+
19
+ monitor.printStats(options);
20
+
21
+ return monitor.getStats();
22
+ }
23
+
24
+ /**
25
+ * Clear all cache entries
26
+ */
27
+ export async function clearCache() {
28
+ const cache = getCache();
29
+ const sizeBefore = cache.size();
30
+
31
+ cache.clear();
32
+
33
+ console.log(chalk.green(`✓ Cache cleared (${sizeBefore} entries removed)`));
34
+ }
35
+
36
+ /**
37
+ * Reset cache instance
38
+ */
39
+ export async function resetCacheInstance() {
40
+ resetCache();
41
+ console.log(chalk.green('✓ Cache instance reset'));
42
+ }
43
+
44
+ /**
45
+ * Show cache entries
46
+ * @param {Object} options - Options
47
+ * @param {number} [options.limit=10] - Maximum entries to show
48
+ */
49
+ export async function listCacheEntries(options = {}) {
50
+ const cache = getCache();
51
+ const limit = options.limit || 10;
52
+ const keys = cache.keys();
53
+
54
+ console.log(chalk.bold.cyan(`\n=== Cache Entries (${keys.length} total) ===\n`));
55
+
56
+ if (keys.length === 0) {
57
+ console.log(chalk.gray(' (empty)'));
58
+ return;
59
+ }
60
+
61
+ const displayKeys = keys.slice(0, limit);
62
+
63
+ displayKeys.forEach((key, index) => {
64
+ const valid = cache.isValid(key);
65
+ const status = valid ? chalk.green('✓') : chalk.red('✗');
66
+ console.log(` ${status} ${chalk.gray(`[${index + 1}]`)} ${key}`);
67
+ });
68
+
69
+ if (keys.length > limit) {
70
+ console.log(chalk.gray(`\n ... and ${keys.length - limit} more`));
71
+ }
72
+
73
+ console.log('');
74
+ }
75
+
76
+ /**
77
+ * Export cache statistics to JSON
78
+ * @param {string} [outputPath] - Output file path
79
+ */
80
+ export async function exportCacheStats(outputPath) {
81
+ const cache = getCache();
82
+ const monitor = new CacheMonitor(cache);
83
+ const json = monitor.toJSON();
84
+
85
+ if (outputPath) {
86
+ const fs = await import('fs');
87
+ fs.writeFileSync(outputPath, json, 'utf-8');
88
+ console.log(chalk.green(`✓ Cache statistics exported to ${outputPath}`));
89
+ } else {
90
+ console.log(json);
91
+ }
92
+
93
+ return json;
94
+ }
95
+
96
+ /**
97
+ * Benchmark cache performance
98
+ */
99
+ export async function benchmarkCache() {
100
+ console.log(chalk.bold.cyan('\n=== Running Cache Benchmark ===\n'));
101
+
102
+ const { default: parseScriptFile } = await import('../parsers/parseScriptsMd.cached.js');
103
+ const cache = getCache();
104
+ const monitor = new CacheMonitor(cache);
105
+
106
+ // Cold cache
107
+ console.log(chalk.yellow('Testing cold cache...'));
108
+ cache.clear();
109
+ const coldStart = performance.now();
110
+ await parseScriptFile();
111
+ const coldTime = performance.now() - coldStart;
112
+ monitor.recordColdCache(coldTime);
113
+
114
+ console.log(chalk.green(` Cold cache: ${coldTime.toFixed(2)}ms`));
115
+
116
+ // Warm cache (5 iterations)
117
+ console.log(chalk.yellow('\nTesting warm cache (5 iterations)...'));
118
+ const warmTimes = [];
119
+
120
+ for (let i = 0; i < 5; i++) {
121
+ const warmStart = performance.now();
122
+ await parseScriptFile();
123
+ const warmTime = performance.now() - warmStart;
124
+ warmTimes.push(warmTime);
125
+ monitor.recordWarmCache(warmTime);
126
+ }
127
+
128
+ const avgWarmTime = warmTimes.reduce((a, b) => a + b, 0) / warmTimes.length;
129
+ const speedup = coldTime / avgWarmTime;
130
+
131
+ console.log(chalk.green(` Warm cache (avg): ${avgWarmTime.toFixed(2)}ms`));
132
+ console.log(chalk.bold.green(` Speedup: ${speedup.toFixed(2)}x`));
133
+
134
+ if (speedup >= 10) {
135
+ console.log(chalk.bold.green('\n ✓ Target achieved (10x speedup)!'));
136
+ } else {
137
+ console.log(chalk.bold.yellow(`\n ⚠ Below target (${speedup.toFixed(2)}x < 10x)`));
138
+ }
139
+
140
+ console.log('');
141
+
142
+ return { coldTime, avgWarmTime, speedup };
143
+ }
144
+
145
+ export default {
146
+ showCacheStats,
147
+ clearCache,
148
+ resetCacheInstance,
149
+ listCacheEntries,
150
+ exportCacheStats,
151
+ benchmarkCache
152
+ };