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.
- package/README.md +48 -30
- package/dist/index.js +502 -185
- package/dist/lib/auth/auth-conf.js +49 -45
- package/dist/lib/cache/README.md +341 -0
- package/dist/lib/cache/cli.js +152 -0
- package/dist/lib/cache/file-watcher.js +193 -0
- package/dist/lib/cache/index.js +422 -0
- package/dist/lib/cache/monitor.js +224 -0
- package/dist/lib/commands/doctor.js +225 -0
- package/dist/lib/completions/completion.js +342 -0
- package/dist/lib/completions/generator.js +152 -0
- package/dist/lib/completions/scripts/bash.sh +108 -0
- package/dist/lib/completions/scripts/fish.sh +105 -0
- package/dist/lib/completions/scripts/powershell.ps1 +168 -0
- package/dist/lib/completions/scripts/zsh.sh +124 -0
- package/dist/lib/diagnostics/cache.js +121 -0
- package/dist/lib/diagnostics/fileSystem.js +236 -0
- package/dist/lib/diagnostics/gitCheck.js +41 -0
- package/dist/lib/diagnostics/nodeVersion.js +68 -0
- package/dist/lib/diagnostics/packageManager.js +64 -0
- package/dist/lib/diagnostics/performance.js +141 -0
- package/dist/lib/encryption/decryptConfig.js +3 -2
- package/dist/lib/encryption/encryption.js +153 -113
- package/dist/lib/generators/generateFScripts.js +16 -13
- package/dist/lib/generators/generateToc.js +23 -14
- package/dist/lib/generators/index.js +1 -1
- package/dist/lib/git/pub.js +27 -31
- package/dist/lib/git/taskRunner.js +79 -69
- package/dist/lib/git/validateNotDev.js +65 -54
- package/dist/lib/optionList.js +69 -57
- package/dist/lib/parsers/parseScriptsMd.cached.js +208 -0
- package/dist/lib/parsers/parseScriptsMd.js +88 -79
- package/dist/lib/parsers/parseScriptsPackage.js +4 -3
- package/dist/lib/performance/cache.js +199 -0
- package/dist/lib/performance/lazy-loader.js +189 -0
- package/dist/lib/performance/monitor.js +303 -0
- package/dist/lib/plugins/deployment/index.js +113 -0
- package/dist/lib/plugins/hooks.js +17 -0
- package/dist/lib/plugins/loader.js +91 -0
- package/dist/lib/plugins/task-notifier/index.js +72 -0
- package/dist/lib/release/bump.js +51 -43
- package/dist/lib/release/commitWithMessage.js +80 -52
- package/dist/lib/release/publish.js +19 -14
- package/dist/lib/release/pushToGit.js +40 -31
- package/dist/lib/release/releasenotes.js +116 -97
- package/dist/lib/release/seeChangedFiles.js +68 -60
- package/dist/lib/release/sort.js +200 -116
- package/dist/lib/release/tree.js +161 -147
- package/dist/lib/release/validateNotDev.js +52 -44
- package/dist/lib/running/index.js +1 -1
- package/dist/lib/running/runCLICommand.js +41 -31
- package/dist/lib/running/runParallel.js +61 -59
- package/dist/lib/running/runSequence.js +55 -53
- package/dist/lib/startScripts.js +129 -114
- package/dist/lib/taskList.js +99 -84
- package/dist/lib/test-files/.fscripts.md +113 -0
- package/dist/lib/test-files/.fscripts.test.md +103 -0
- package/dist/lib/test-files/.fscriptsb.md +107 -0
- package/dist/lib/test-files/.mdtest.md +40 -0
- package/dist/lib/test-files/consoleSample.js +17 -0
- package/dist/lib/test-files/inputSample.js +20 -0
- package/dist/lib/test-files/testConsole.js +1 -0
- package/dist/lib/test-files/testInput.js +2 -0
- package/dist/lib/upgradePackages.js +56 -46
- package/dist/lib/utils/clear.js +16 -13
- package/dist/lib/utils/console.js +27 -21
- package/dist/lib/utils/encryption.js +55 -13
- package/dist/lib/utils/hash.js +128 -0
- package/dist/lib/utils/helpers.js +153 -142
- package/dist/lib/utils/index.js +1 -1
- package/dist/lib/utils/prompt.js +24 -29
- package/package.json +20 -32
- package/dist/lib/codemod/arrow.js +0 -13
- package/dist/lib/codemod/arrow2.js +0 -67
- package/dist/lib/codemod/funcs.js +0 -25
- package/dist/lib/codemod/removeConsole.js +0 -12
- package/dist/lib/codemod/test.js +0 -8
- package/dist/lib/components/App.js +0 -64
- package/dist/lib/components/Selector.js +0 -133
- package/dist/lib/components/TabChanger.js +0 -113
- package/dist/lib/components/Table.js +0 -177
- package/dist/lib/components/Tabs.js +0 -221
- package/dist/lib/generateFScripts.js +0 -25
- package/dist/lib/generateToc.js +0 -30
- package/dist/lib/helpers.js +0 -191
- package/dist/lib/parseScriptsMd.js +0 -85
- package/dist/lib/parseScriptsPackage.js +0 -9
- package/dist/lib/release/index.js +0 -4
- package/dist/lib/run/lib.js +0 -454
- package/dist/lib/run/main-p.js +0 -59
- package/dist/lib/run/main-s.js +0 -56
- package/dist/lib/run/parse-cli-args.js +0 -222
- package/dist/lib/run/run-p.js +0 -30
- package/dist/lib/run/run-s.js +0 -57
- package/dist/lib/runCLICommand.js +0 -30
- package/dist/lib/runParallel.js +0 -20
- package/dist/lib/runSequence.js +0 -38
- 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
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
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
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
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
|
-
|
|
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
|
+
};
|