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
@@ -0,0 +1,224 @@
1
+ /**
2
+ * Cache monitoring and statistics
3
+ * @module cache/monitor
4
+ */
5
+
6
+ import chalk from 'chalk';
7
+
8
+ /**
9
+ * CacheMonitor - Collects and displays cache performance metrics
10
+ * @class
11
+ */
12
+ class CacheMonitor {
13
+ /**
14
+ * Create a cache monitor
15
+ * @param {CacheManager} cacheManager - Cache manager instance
16
+ * @param {FileWatcher} [fileWatcher] - Optional file watcher instance
17
+ */
18
+ constructor(cacheManager, fileWatcher = null) {
19
+ this.cacheManager = cacheManager;
20
+ this.fileWatcher = fileWatcher;
21
+
22
+ // Performance tracking
23
+ this.metrics = {
24
+ coldCacheTime: [],
25
+ warmCacheTime: [],
26
+ avgColdTime: 0,
27
+ avgWarmTime: 0,
28
+ speedup: 0
29
+ };
30
+
31
+ // Listen to cache events
32
+ this._attachListeners();
33
+ }
34
+
35
+ /**
36
+ * Attach event listeners to cache manager
37
+ * @private
38
+ */
39
+ _attachListeners() {
40
+ this.cacheManager.on('hit', () => {
41
+ // Cache hit event
42
+ });
43
+
44
+ this.cacheManager.on('miss', () => {
45
+ // Cache miss event
46
+ });
47
+
48
+ this.cacheManager.on('invalidate', ({ key }) => {
49
+ // Invalidation event
50
+ });
51
+
52
+ this.cacheManager.on('evict', ({ key }) => {
53
+ // Eviction event
54
+ });
55
+
56
+ this.cacheManager.on('cleanup', ({ count }) => {
57
+ // Cleanup event
58
+ });
59
+ }
60
+
61
+ /**
62
+ * Record a cold cache operation time
63
+ * @param {number} timeMs - Time in milliseconds
64
+ */
65
+ recordColdCache(timeMs) {
66
+ this.metrics.coldCacheTime.push(timeMs);
67
+ this._updateAverages();
68
+ }
69
+
70
+ /**
71
+ * Record a warm cache operation time
72
+ * @param {number} timeMs - Time in milliseconds
73
+ */
74
+ recordWarmCache(timeMs) {
75
+ this.metrics.warmCacheTime.push(timeMs);
76
+ this._updateAverages();
77
+ }
78
+
79
+ /**
80
+ * Update average times and speedup
81
+ * @private
82
+ */
83
+ _updateAverages() {
84
+ if (this.metrics.coldCacheTime.length > 0) {
85
+ const sum = this.metrics.coldCacheTime.reduce((a, b) => a + b, 0);
86
+ this.metrics.avgColdTime = sum / this.metrics.coldCacheTime.length;
87
+ }
88
+
89
+ if (this.metrics.warmCacheTime.length > 0) {
90
+ const sum = this.metrics.warmCacheTime.reduce((a, b) => a + b, 0);
91
+ this.metrics.avgWarmTime = sum / this.metrics.warmCacheTime.length;
92
+ }
93
+
94
+ if (this.metrics.avgWarmTime > 0 && this.metrics.avgColdTime > 0) {
95
+ this.metrics.speedup = this.metrics.avgColdTime / this.metrics.avgWarmTime;
96
+ }
97
+ }
98
+
99
+ /**
100
+ * Get comprehensive statistics
101
+ * @returns {Object} Statistics object
102
+ */
103
+ getStats() {
104
+ const cacheStats = this.cacheManager.getStats();
105
+ const watcherStats = this.fileWatcher ? this.fileWatcher.getStats() : null;
106
+
107
+ return {
108
+ cache: cacheStats,
109
+ watcher: watcherStats,
110
+ performance: {
111
+ avgColdTime: Math.round(this.metrics.avgColdTime),
112
+ avgWarmTime: Math.round(this.metrics.avgWarmTime),
113
+ speedup: this.metrics.speedup.toFixed(2) + 'x',
114
+ coldCacheSamples: this.metrics.coldCacheTime.length,
115
+ warmCacheSamples: this.metrics.warmCacheTime.length
116
+ }
117
+ };
118
+ }
119
+
120
+ /**
121
+ * Print statistics to console
122
+ * @param {Object} [options] - Display options
123
+ * @param {boolean} [options.verbose=false] - Show detailed stats
124
+ */
125
+ printStats(options = {}) {
126
+ const verbose = options.verbose || false;
127
+ const stats = this.getStats();
128
+
129
+ console.log('\n' + chalk.bold.cyan('=== Cache Statistics ==='));
130
+
131
+ // Cache stats
132
+ console.log(chalk.bold('\nCache:'));
133
+ console.log(` Size: ${chalk.green(stats.cache.size)}/${stats.cache.maxSize}`);
134
+ console.log(` Hits: ${chalk.green(stats.cache.hits)}`);
135
+ console.log(` Misses: ${chalk.yellow(stats.cache.misses)}`);
136
+ console.log(` Hit Rate: ${this._colorizeHitRate(stats.cache.hitRate)}%`);
137
+ console.log(` Invalidations: ${chalk.yellow(stats.cache.invalidations)}`);
138
+ console.log(` Evictions: ${chalk.yellow(stats.cache.evictions)}`);
139
+
140
+ // Performance stats
141
+ if (stats.performance.warmCacheSamples > 0) {
142
+ console.log(chalk.bold('\nPerformance:'));
143
+ console.log(` Cold Cache: ${chalk.yellow(stats.performance.avgColdTime + 'ms')}`);
144
+ console.log(` Warm Cache: ${chalk.green(stats.performance.avgWarmTime + 'ms')}`);
145
+ console.log(` Speedup: ${chalk.bold.green(stats.performance.speedup)}`);
146
+ }
147
+
148
+ // File watcher stats
149
+ if (stats.watcher) {
150
+ console.log(chalk.bold('\nFile Watcher:'));
151
+ console.log(` Files Watched: ${chalk.green(stats.watcher.filesWatched)}`);
152
+ console.log(` Change Events: ${chalk.yellow(stats.watcher.changeEvents)}`);
153
+ console.log(` Invalidations: ${chalk.yellow(stats.watcher.invalidations)}`);
154
+
155
+ if (verbose && stats.watcher.watchedFiles.length > 0) {
156
+ console.log(chalk.bold('\n Watched Files:'));
157
+ stats.watcher.watchedFiles.forEach(file => {
158
+ console.log(` - ${chalk.gray(file)}`);
159
+ });
160
+ }
161
+ }
162
+
163
+ // Uptime
164
+ const uptimeMinutes = Math.floor(stats.cache.uptime / 60000);
165
+ console.log(chalk.bold('\nUptime:'), chalk.green(`${uptimeMinutes} minutes`));
166
+
167
+ console.log(chalk.bold.cyan('\n========================\n'));
168
+ }
169
+
170
+ /**
171
+ * Colorize hit rate based on percentage
172
+ * @private
173
+ * @param {string|number} hitRate - Hit rate percentage
174
+ * @returns {string} Colored hit rate
175
+ */
176
+ _colorizeHitRate(hitRate) {
177
+ const rate = parseFloat(hitRate);
178
+ if (rate >= 80) return chalk.green(hitRate);
179
+ if (rate >= 50) return chalk.yellow(hitRate);
180
+ return chalk.red(hitRate);
181
+ }
182
+
183
+ /**
184
+ * Get summary statistics as a single line
185
+ * @returns {string} Summary string
186
+ */
187
+ getSummary() {
188
+ const stats = this.getStats();
189
+ const parts = [
190
+ `${stats.cache.size} entries`,
191
+ `${stats.cache.hitRate}% hit rate`
192
+ ];
193
+
194
+ if (stats.performance.warmCacheSamples > 0) {
195
+ parts.push(`${stats.performance.speedup} speedup`);
196
+ }
197
+
198
+ return parts.join(', ');
199
+ }
200
+
201
+ /**
202
+ * Export statistics as JSON
203
+ * @returns {string} JSON string
204
+ */
205
+ toJSON() {
206
+ return JSON.stringify(this.getStats(), null, 2);
207
+ }
208
+
209
+ /**
210
+ * Reset all metrics
211
+ */
212
+ resetMetrics() {
213
+ this.metrics = {
214
+ coldCacheTime: [],
215
+ warmCacheTime: [],
216
+ avgColdTime: 0,
217
+ avgWarmTime: 0,
218
+ speedup: 0
219
+ };
220
+ this.cacheManager.resetStats();
221
+ }
222
+ }
223
+
224
+ export default CacheMonitor;
@@ -0,0 +1,225 @@
1
+ import chalk from 'chalk';
2
+ import boxen from 'boxen';
3
+ import { checkNodeVersion } from '../diagnostics/nodeVersion.js';
4
+ import { checkPackageManager } from '../diagnostics/packageManager.js';
5
+ import { checkGit } from '../diagnostics/gitCheck.js';
6
+ import {
7
+ checkFScriptsFile,
8
+ checkPackageJson,
9
+ checkTypeScript,
10
+ checkFilePermissions
11
+ } from '../diagnostics/fileSystem.js';
12
+ import { checkCache } from '../diagnostics/cache.js';
13
+ import { checkStartupTime, checkMemoryUsage } from '../diagnostics/performance.js';
14
+
15
+ /**
16
+ * Run all diagnostic checks
17
+ * @param {Object} options - Command options
18
+ * @returns {Promise<Object>} Results object
19
+ */
20
+ export async function runDiagnostics(options = {}) {
21
+ const { fix = false, json = false } = options;
22
+
23
+ console.log(chalk.cyan.bold('\n🔍 Running FSCR diagnostics...\n'));
24
+
25
+ const checks = [
26
+ { name: 'nodeVersion', fn: checkNodeVersion, critical: true },
27
+ { name: 'packageManager', fn: checkPackageManager, critical: true },
28
+ { name: 'git', fn: checkGit, critical: false },
29
+ { name: 'fscriptsFile', fn: checkFScriptsFile, critical: false },
30
+ { name: 'packageJson', fn: checkPackageJson, critical: true },
31
+ { name: 'typescript', fn: checkTypeScript, critical: false },
32
+ { name: 'filePermissions', fn: checkFilePermissions, critical: true },
33
+ { name: 'cache', fn: checkCache, critical: false },
34
+ { name: 'startupTime', fn: checkStartupTime, critical: false },
35
+ { name: 'memoryUsage', fn: checkMemoryUsage, critical: false }
36
+ ];
37
+
38
+ const results = [];
39
+ let passedCount = 0;
40
+ let warningCount = 0;
41
+ let errorCount = 0;
42
+ let fixedCount = 0;
43
+
44
+ for (const check of checks) {
45
+ try {
46
+ const result = await check.fn();
47
+ results.push({ ...result, critical: check.critical });
48
+
49
+ // Display result
50
+ displayCheckResult(result);
51
+
52
+ // Count results
53
+ if (result.passed && !result.warning) {
54
+ passedCount++;
55
+ } else if (result.warning) {
56
+ warningCount++;
57
+ } else {
58
+ errorCount++;
59
+ }
60
+
61
+ // Auto-fix if requested
62
+ if (fix && !result.passed && result.canFix && result.fix) {
63
+ try {
64
+ console.log(chalk.yellow(` Attempting to fix...`));
65
+ const fixMessage = await result.fix();
66
+ console.log(chalk.green(` ✓ Fixed: ${fixMessage}\n`));
67
+ fixedCount++;
68
+ } catch (fixError) {
69
+ console.log(chalk.red(` ✗ Fix failed: ${fixError.message}\n`));
70
+ }
71
+ } else if (!result.passed && result.fixInstructions) {
72
+ console.log(chalk.gray(` ${result.fixInstructions}\n`));
73
+ }
74
+ } catch (error) {
75
+ console.log(
76
+ chalk.red(`❌ ${check.name}\n Error: ${error.message}\n`)
77
+ );
78
+ errorCount++;
79
+ results.push({
80
+ name: check.name,
81
+ passed: false,
82
+ error: error.message,
83
+ critical: check.critical
84
+ });
85
+ }
86
+ }
87
+
88
+ // Display summary (skip if JSON mode)
89
+ if (!json) {
90
+ displaySummary(passedCount, warningCount, errorCount, fixedCount);
91
+ }
92
+
93
+ // Return results object
94
+ return {
95
+ passed: errorCount === 0,
96
+ summary: {
97
+ passed: passedCount,
98
+ warnings: warningCount,
99
+ errors: errorCount,
100
+ fixed: fixedCount,
101
+ total: checks.length
102
+ },
103
+ results
104
+ };
105
+ }
106
+
107
+ /**
108
+ * Display check result
109
+ * @param {Object} result - Check result
110
+ */
111
+ function displayCheckResult(result) {
112
+ let icon = '✅';
113
+ let color = 'green';
114
+
115
+ if (!result.passed) {
116
+ icon = '❌';
117
+ color = 'red';
118
+ } else if (result.warning) {
119
+ icon = '⚠️ ';
120
+ color = 'yellow';
121
+ }
122
+
123
+ console.log(chalk[color](`${icon} ${result.name}`));
124
+ console.log(chalk.gray(` ${result.message}\n`));
125
+ }
126
+
127
+ /**
128
+ * Display summary
129
+ * @param {number} passed - Number of passed checks
130
+ * @param {number} warnings - Number of warnings
131
+ * @param {number} errors - Number of errors
132
+ * @param {number} fixed - Number of fixed issues
133
+ */
134
+ function displaySummary(passed, warnings, errors, fixed) {
135
+ console.log(chalk.gray('─'.repeat(50)));
136
+ console.log(chalk.bold('Summary:'));
137
+
138
+ if (passed > 0) {
139
+ console.log(chalk.green(` ✅ Passed: ${passed}`));
140
+ }
141
+
142
+ if (warnings > 0) {
143
+ console.log(chalk.yellow(` ⚠️ Warnings: ${warnings}`));
144
+ }
145
+
146
+ if (errors > 0) {
147
+ console.log(chalk.red(` ❌ Errors: ${errors}`));
148
+ }
149
+
150
+ if (fixed > 0) {
151
+ console.log(chalk.cyan(` 🔧 Fixed: ${fixed}`));
152
+ }
153
+
154
+ console.log(chalk.gray('─'.repeat(50)));
155
+
156
+ // Overall status
157
+ if (errors === 0 && warnings === 0) {
158
+ console.log(
159
+ boxen(chalk.green.bold('✓ All checks passed!'), {
160
+ padding: 1,
161
+ margin: 1,
162
+ borderStyle: 'round',
163
+ borderColor: 'green'
164
+ })
165
+ );
166
+ } else if (errors === 0) {
167
+ console.log(
168
+ boxen(chalk.yellow.bold('⚠ System operational with warnings'), {
169
+ padding: 1,
170
+ margin: 1,
171
+ borderStyle: 'round',
172
+ borderColor: 'yellow'
173
+ })
174
+ );
175
+ } else {
176
+ console.log(
177
+ boxen(chalk.red.bold('✗ Issues found - please review above'), {
178
+ padding: 1,
179
+ margin: 1,
180
+ borderStyle: 'round',
181
+ borderColor: 'red'
182
+ })
183
+ );
184
+ console.log(
185
+ chalk.gray(
186
+ '\nTip: Run "fsr doctor --fix" to automatically fix some issues\n'
187
+ )
188
+ );
189
+ }
190
+ }
191
+
192
+ /**
193
+ * Doctor command handler
194
+ * @param {Object} argv - Command arguments
195
+ */
196
+ export default async function doctor(argv) {
197
+ try {
198
+ const options = {
199
+ fix: argv.fix || false,
200
+ json: argv.json || false
201
+ };
202
+
203
+ const result = await runDiagnostics(options);
204
+
205
+ if (options.json) {
206
+ console.log(JSON.stringify(result, null, 2));
207
+ }
208
+
209
+ // Exit with error code if there are critical failures
210
+ if (!result.passed) {
211
+ const criticalFailures = result.results.filter(
212
+ (r) => !r.passed && r.critical
213
+ );
214
+ if (criticalFailures.length > 0) {
215
+ process.exit(1);
216
+ }
217
+ }
218
+ } catch (error) {
219
+ console.error(chalk.red.bold(`\n❌ Doctor command failed: ${error.message}\n`));
220
+ if (argv.verbose) {
221
+ console.error(error.stack);
222
+ }
223
+ process.exit(1);
224
+ }
225
+ }