mastercontroller 1.2.13 → 1.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 (38) hide show
  1. package/.claude/settings.local.json +12 -0
  2. package/MasterAction.js +7 -7
  3. package/MasterControl.js +192 -122
  4. package/MasterCors.js +29 -0
  5. package/MasterHtml.js +5 -5
  6. package/MasterPipeline.js +344 -0
  7. package/MasterRouter.js +59 -29
  8. package/MasterSession.js +19 -0
  9. package/MasterTemplate.js +3 -3
  10. package/MasterTimeout.js +332 -0
  11. package/README.md +1496 -36
  12. package/docs/timeout-and-error-handling.md +712 -0
  13. package/{MasterError.js → error/MasterError.js} +2 -2
  14. package/{MasterErrorLogger.js → error/MasterErrorLogger.js} +1 -1
  15. package/{MasterErrorMiddleware.js → error/MasterErrorMiddleware.js} +2 -2
  16. package/error/MasterErrorRenderer.js +529 -0
  17. package/{ssr → error}/SSRErrorHandler.js +2 -2
  18. package/{MasterCache.js → monitoring/MasterCache.js} +2 -2
  19. package/{MasterMemoryMonitor.js → monitoring/MasterMemoryMonitor.js} +2 -2
  20. package/{MasterProfiler.js → monitoring/MasterProfiler.js} +2 -2
  21. package/{ssr → monitoring}/PerformanceMonitor.js +2 -2
  22. package/package.json +5 -5
  23. package/{EventHandlerValidator.js → security/EventHandlerValidator.js} +3 -3
  24. package/{MasterSanitizer.js → security/MasterSanitizer.js} +2 -2
  25. package/{MasterValidator.js → security/MasterValidator.js} +2 -2
  26. package/{SecurityMiddleware.js → security/SecurityMiddleware.js} +75 -3
  27. package/{SessionSecurity.js → security/SessionSecurity.js} +2 -2
  28. package/ssr/hydration-client.js +3 -3
  29. package/ssr/runtime-ssr.cjs +9 -9
  30. package/MasterBenchmark.js +0 -89
  31. package/MasterBuildOptimizer.js +0 -376
  32. package/MasterBundleAnalyzer.js +0 -108
  33. package/ssr/HTMLUtils.js +0 -15
  34. /package/{ssr → error}/ErrorBoundary.js +0 -0
  35. /package/{ssr → error}/HydrationMismatch.js +0 -0
  36. /package/{MasterBackendErrorHandler.js → error/MasterBackendErrorHandler.js} +0 -0
  37. /package/{MasterErrorHandler.js → error/MasterErrorHandler.js} +0 -0
  38. /package/{CSPConfig.js → security/CSPConfig.js} +0 -0
@@ -1,4 +1,4 @@
1
- // version 1.0.0
1
+ // version 1.0.1
2
2
  // MasterController Security Middleware - CSRF, Headers, Rate Limiting, CORS
3
3
 
4
4
  /**
@@ -7,7 +7,7 @@
7
7
  */
8
8
 
9
9
  const crypto = require('crypto');
10
- const { logger } = require('./MasterErrorLogger');
10
+ const { logger } = require('../error/MasterErrorLogger');
11
11
 
12
12
  // Rate limiting store
13
13
  const rateLimitStore = new Map();
@@ -473,6 +473,73 @@ function validateCSRFToken(token) {
473
473
  return security.validateCSRFToken(token);
474
474
  }
475
475
 
476
+ /**
477
+ * Pipeline-compatible middleware wrappers
478
+ * These adapt from (ctx, next) format to (req, res, next) format
479
+ */
480
+
481
+ function pipelineSecurityHeaders(options = {}) {
482
+ const instance = options.instance || security;
483
+ return async (ctx, next) => {
484
+ // Create next callback for old-style middleware
485
+ let nextCalled = false;
486
+ const oldNext = () => { nextCalled = true; };
487
+
488
+ // Call old middleware
489
+ instance.securityHeadersMiddleware(ctx.request, ctx.response, oldNext);
490
+
491
+ // Continue pipeline if next was called
492
+ if (nextCalled) {
493
+ await next();
494
+ }
495
+ };
496
+ }
497
+
498
+ function pipelineCors(options = {}) {
499
+ const instance = new SecurityMiddleware({ ...options, headers: false, csrf: false, rateLimit: false });
500
+ return async (ctx, next) => {
501
+ let nextCalled = false;
502
+ const oldNext = () => { nextCalled = true; };
503
+
504
+ instance.corsMiddleware(ctx.request, ctx.response, oldNext);
505
+
506
+ // CORS might terminate for OPTIONS - check if response ended
507
+ if (!ctx.response.writableEnded && nextCalled) {
508
+ await next();
509
+ }
510
+ };
511
+ }
512
+
513
+ function pipelineRateLimit(options = {}) {
514
+ const instance = new SecurityMiddleware({ ...options, headers: false, csrf: false, cors: false });
515
+ return async (ctx, next) => {
516
+ let nextCalled = false;
517
+ const oldNext = () => { nextCalled = true; };
518
+
519
+ instance.rateLimitMiddleware(ctx.request, ctx.response, oldNext);
520
+
521
+ // Rate limit might terminate - check if response ended
522
+ if (!ctx.response.writableEnded && nextCalled) {
523
+ await next();
524
+ }
525
+ };
526
+ }
527
+
528
+ function pipelineCsrf(options = {}) {
529
+ const instance = new SecurityMiddleware({ ...options, headers: false, cors: false, rateLimit: false });
530
+ return async (ctx, next) => {
531
+ let nextCalled = false;
532
+ const oldNext = () => { nextCalled = true; };
533
+
534
+ instance.csrfMiddleware(ctx.request, ctx.response, oldNext);
535
+
536
+ // CSRF might terminate - check if response ended
537
+ if (!ctx.response.writableEnded && nextCalled) {
538
+ await next();
539
+ }
540
+ };
541
+ }
542
+
476
543
  module.exports = {
477
544
  SecurityMiddleware,
478
545
  security,
@@ -482,5 +549,10 @@ module.exports = {
482
549
  csrf,
483
550
  generateCSRFToken,
484
551
  validateCSRFToken,
485
- SECURITY_HEADERS
552
+ SECURITY_HEADERS,
553
+ // Pipeline-compatible exports
554
+ pipelineSecurityHeaders,
555
+ pipelineCors,
556
+ pipelineRateLimit,
557
+ pipelineCsrf
486
558
  };
@@ -1,4 +1,4 @@
1
- // version 1.0.0
1
+ // version 1.0.1
2
2
  // MasterController Session Security - Secure cookie handling, session fixation prevention
3
3
 
4
4
  /**
@@ -7,7 +7,7 @@
7
7
  */
8
8
 
9
9
  const crypto = require('crypto');
10
- const { logger } = require('./MasterErrorLogger');
10
+ const { logger } = require('../error/MasterErrorLogger');
11
11
 
12
12
  // Session store (use Redis in production)
13
13
  const sessionStore = new Map();
@@ -1,11 +1,11 @@
1
1
  /**
2
2
  * MasterController Client-Side Hydration Runtime
3
3
  * Handles error boundaries and hydration mismatch detection
4
- * Version: 2.0.0
4
+ * Version: 2.0.1
5
5
  */
6
6
 
7
7
  // Import error boundary
8
- import { ErrorBoundary } from './ErrorBoundary.js';
8
+ import { ErrorBoundary } from '../error/ErrorBoundary.js';
9
9
 
10
10
  // Import hydration mismatch detection
11
11
  const isDevelopment = window.location.hostname === 'localhost' ||
@@ -13,7 +13,7 @@ const isDevelopment = window.location.hostname === 'localhost' ||
13
13
 
14
14
  if (isDevelopment && typeof require !== 'undefined') {
15
15
  try {
16
- const { enableHydrationMismatchDetection } = require('./HydrationMismatch.js');
16
+ const { enableHydrationMismatchDetection } = require('../error/HydrationMismatch.js');
17
17
  enableHydrationMismatchDetection({
18
18
  verbose: localStorage.getItem('mc-hydration-debug') === 'true',
19
19
  delay: 1000
@@ -13,18 +13,18 @@ const vm = require('vm');
13
13
  const moduleCache = new Map();
14
14
 
15
15
  // Error handling and monitoring
16
- const { MasterControllerError, findSimilarStrings } = require('../MasterErrorHandler');
17
- const { safeRenderComponent, validateSSRComponent, wrapConnectedCallback } = require('./SSRErrorHandler');
18
- const { monitor } = require('./PerformanceMonitor');
19
- const { logger } = require('../MasterErrorLogger');
16
+ const { MasterControllerError, findSimilarStrings } = require('../error/MasterErrorHandler');
17
+ const { safeRenderComponent, validateSSRComponent, wrapConnectedCallback } = require('../error/SSRErrorHandler');
18
+ const { monitor } = require('../monitoring/PerformanceMonitor');
19
+ const { logger } = require('../error/MasterErrorLogger');
20
20
 
21
21
  // Security - Sanitization and validation
22
- const { sanitizer, sanitizeTemplateHTML, sanitizeProps } = require('../MasterSanitizer');
23
- const { validateEventAttribute } = require('../EventHandlerValidator');
22
+ const { sanitizer, sanitizeTemplateHTML, sanitizeProps } = require('../security/MasterSanitizer');
23
+ const { validateEventAttribute } = require('../security/EventHandlerValidator');
24
24
 
25
25
  // Performance - Caching and profiling
26
- const { cache } = require('../MasterCache');
27
- const { profiler } = require('../MasterProfiler');
26
+ const { cache } = require('../monitoring/MasterCache');
27
+ const { profiler } = require('../monitoring/MasterProfiler');
28
28
 
29
29
  // Track registered custom elements to detect duplicates
30
30
  const registeredElements = new Map();
@@ -462,7 +462,7 @@ module.exports = async function compileWebComponentsHTML(inputHTML, preloadModul
462
462
  if (isDevelopment) {
463
463
  el.innerHTML = error.toHTML();
464
464
  } else {
465
- const { renderFallback } = require('./SSRErrorHandler');
465
+ const { renderFallback } = require('../error/SSRErrorHandler');
466
466
  el.innerHTML = renderFallback(componentName);
467
467
  }
468
468
  }
@@ -1,89 +0,0 @@
1
- // version 1.0.0
2
- // MasterController Benchmark - Performance Benchmarking
3
-
4
- const { profiler } = require('./MasterProfiler');
5
- const { logger } = require('./MasterErrorLogger');
6
-
7
- class MasterBenchmark {
8
- constructor() {
9
- this.results = [];
10
- }
11
-
12
- /**
13
- * Benchmark SSR render time
14
- */
15
- async benchmarkSSR(component, iterations = 100) {
16
- const times = [];
17
-
18
- for (let i = 0; i < iterations; i++) {
19
- const start = Date.now();
20
-
21
- // Render component (would call actual SSR here)
22
- await new Promise(resolve => setImmediate(resolve));
23
-
24
- const duration = Date.now() - start;
25
- times.push(duration);
26
- }
27
-
28
- return this.calculateStats(times, 'SSR Render');
29
- }
30
-
31
- /**
32
- * Benchmark hydration time
33
- */
34
- async benchmarkHydration(iterations = 100) {
35
- const times = [];
36
-
37
- for (let i = 0; i < iterations; i++) {
38
- const start = Date.now();
39
-
40
- // Simulate hydration
41
- await new Promise(resolve => setImmediate(resolve));
42
-
43
- const duration = Date.now() - start;
44
- times.push(duration);
45
- }
46
-
47
- return this.calculateStats(times, 'Hydration');
48
- }
49
-
50
- /**
51
- * Calculate statistics
52
- */
53
- calculateStats(times, name) {
54
- const sorted = times.sort((a, b) => a - b);
55
- const sum = times.reduce((a, b) => a + b, 0);
56
-
57
- return {
58
- name,
59
- iterations: times.length,
60
- min: sorted[0],
61
- max: sorted[sorted.length - 1],
62
- mean: sum / times.length,
63
- median: sorted[Math.floor(times.length / 2)],
64
- p95: sorted[Math.floor(times.length * 0.95)],
65
- p99: sorted[Math.floor(times.length * 0.99)]
66
- };
67
- }
68
-
69
- /**
70
- * Print benchmark results
71
- */
72
- printResults(stats) {
73
- console.log('\n═══════════════════════════════════════════════════');
74
- console.log('⚡ MasterController Benchmark Results');
75
- console.log('═══════════════════════════════════════════════════');
76
-
77
- console.log(`\n${stats.name} (${stats.iterations} iterations):`);
78
- console.log(` Mean: ${stats.mean.toFixed(2)}ms`);
79
- console.log(` Median: ${stats.median.toFixed(2)}ms`);
80
- console.log(` Min: ${stats.min.toFixed(2)}ms`);
81
- console.log(` Max: ${stats.max.toFixed(2)}ms`);
82
- console.log(` P95: ${stats.p95.toFixed(2)}ms`);
83
- console.log(` P99: ${stats.p99.toFixed(2)}ms`);
84
-
85
- console.log('═══════════════════════════════════════════════════\n');
86
- }
87
- }
88
-
89
- module.exports = { MasterBenchmark };
@@ -1,376 +0,0 @@
1
- // version 1.0.0
2
- // MasterController Build Optimizer - Minification, Tree Shaking, Dead Code Elimination
3
-
4
- /**
5
- * Build-time optimizations for MasterController
6
- * - Minifies event manifests
7
- * - Eliminates dead code
8
- * - Tree shaking for unused components
9
- * - Optimizes bundle size
10
- */
11
-
12
- const fs = require('fs');
13
- const path = require('path');
14
- const { logger } = require('./MasterErrorLogger');
15
-
16
- class MasterBuildOptimizer {
17
- constructor(options = {}) {
18
- this.rootDir = options.rootDir || process.cwd();
19
- this.outputDir = options.outputDir || path.join(this.rootDir, 'public', '__compiled__');
20
- this.minify = options.minify !== false;
21
- this.treeShake = options.treeShake !== false;
22
- this.deadCodeElimination = options.deadCodeElimination !== false;
23
- this.sourceMaps = options.sourceMaps || false;
24
-
25
- // Statistics
26
- this.stats = {
27
- filesProcessed: 0,
28
- bytesOriginal: 0,
29
- bytesOptimized: 0,
30
- timeTaken: 0,
31
- componentsFound: 0,
32
- componentsUsed: 0,
33
- componentsRemoved: 0
34
- };
35
- }
36
-
37
- /**
38
- * Optimize entire build
39
- */
40
- async optimize() {
41
- const startTime = Date.now();
42
-
43
- logger.info({
44
- code: 'MC_PERF_BUILD_START',
45
- message: 'Build optimization started'
46
- });
47
-
48
- try {
49
- // 1. Analyze component usage
50
- const usageMap = await this.analyzeComponentUsage();
51
-
52
- // 2. Tree shake unused components
53
- if (this.treeShake) {
54
- await this.treeShakeComponents(usageMap);
55
- }
56
-
57
- // 3. Minify event manifests
58
- if (this.minify) {
59
- await this.minifyEventManifests();
60
- }
61
-
62
- // 4. Eliminate dead code
63
- if (this.deadCodeElimination) {
64
- await this.eliminateDeadCode();
65
- }
66
-
67
- // 5. Optimize bundle
68
- await this.optimizeBundle();
69
-
70
- this.stats.timeTaken = Date.now() - startTime;
71
-
72
- // Log results
73
- this.logOptimizationResults();
74
-
75
- return this.stats;
76
- } catch (error) {
77
- logger.error({
78
- code: 'MC_PERF_BUILD_ERROR',
79
- message: 'Build optimization failed',
80
- error: error.message
81
- });
82
- throw error;
83
- }
84
- }
85
-
86
- /**
87
- * Analyze which components are actually used in the application
88
- */
89
- async analyzeComponentUsage() {
90
- const usageMap = new Map();
91
-
92
- // Scan all view files
93
- const viewsDir = path.join(this.rootDir, 'app', 'views');
94
- const viewFiles = this.findFiles(viewsDir, ['.html', '.js']);
95
-
96
- for (const file of viewFiles) {
97
- const content = fs.readFileSync(file, 'utf8');
98
-
99
- // Find custom element usages (<ui-button>, <ui-calendar>, etc.)
100
- const customElements = content.match(/<([a-z]+-[a-z-]+)/g) || [];
101
-
102
- for (const match of customElements) {
103
- const tagName = match.substring(1); // Remove <
104
- usageMap.set(tagName, (usageMap.get(tagName) || 0) + 1);
105
- }
106
- }
107
-
108
- this.stats.componentsFound = usageMap.size;
109
-
110
- logger.info({
111
- code: 'MC_PERF_USAGE_ANALYSIS',
112
- message: 'Component usage analysis complete',
113
- componentsFound: usageMap.size
114
- });
115
-
116
- return usageMap;
117
- }
118
-
119
- /**
120
- * Tree shake unused components from the bundle
121
- */
122
- async treeShakeComponents(usageMap) {
123
- const componentsDir = path.join(this.rootDir, 'app', 'assets', 'javascripts', 'shad-web-components', 'components');
124
-
125
- if (!fs.existsSync(componentsDir)) {
126
- return;
127
- }
128
-
129
- const componentFiles = this.findFiles(componentsDir, ['.js']);
130
- let removedCount = 0;
131
-
132
- for (const file of componentFiles) {
133
- const content = fs.readFileSync(file, 'utf8');
134
-
135
- // Extract component tag name from customElements.define call
136
- const defineMatch = content.match(/customElements\.define\(['"]([^'"]+)['"]/);
137
-
138
- if (defineMatch) {
139
- const tagName = defineMatch[1];
140
-
141
- // If component is not used, mark for removal
142
- if (!usageMap.has(tagName)) {
143
- removedCount++;
144
- logger.info({
145
- code: 'MC_PERF_TREE_SHAKE',
146
- message: `Unused component detected: ${tagName}`,
147
- file: path.basename(file)
148
- });
149
-
150
- // In production, we'd actually remove or exclude this from the bundle
151
- // For now, just log it
152
- }
153
- }
154
- }
155
-
156
- this.stats.componentsUsed = usageMap.size;
157
- this.stats.componentsRemoved = removedCount;
158
- }
159
-
160
- /**
161
- * Minify event manifest JSON files
162
- */
163
- async minifyEventManifests() {
164
- const manifestsDir = path.join(this.outputDir, 'event-manifests');
165
-
166
- if (!fs.existsSync(manifestsDir)) {
167
- return;
168
- }
169
-
170
- const manifestFiles = fs.readdirSync(manifestsDir).filter(f => f.endsWith('.json'));
171
-
172
- for (const file of manifestFiles) {
173
- const filePath = path.join(manifestsDir, file);
174
- const content = fs.readFileSync(filePath, 'utf8');
175
- const originalSize = Buffer.byteLength(content, 'utf8');
176
-
177
- // Parse and re-stringify without whitespace
178
- const parsed = JSON.parse(content);
179
- const minified = JSON.stringify(parsed);
180
-
181
- const minifiedSize = Buffer.byteLength(minified, 'utf8');
182
-
183
- // Write minified version
184
- fs.writeFileSync(filePath, minified, 'utf8');
185
-
186
- this.stats.filesProcessed++;
187
- this.stats.bytesOriginal += originalSize;
188
- this.stats.bytesOptimized += minifiedSize;
189
-
190
- logger.info({
191
- code: 'MC_PERF_MINIFY',
192
- message: `Minified ${file}`,
193
- originalSize: originalSize,
194
- minifiedSize: minifiedSize,
195
- savings: `${((1 - minifiedSize / originalSize) * 100).toFixed(1)}%`
196
- });
197
- }
198
- }
199
-
200
- /**
201
- * Eliminate dead code from JavaScript bundles
202
- */
203
- async eliminateDeadCode() {
204
- const jsDir = path.join(this.outputDir);
205
-
206
- if (!fs.existsSync(jsDir)) {
207
- return;
208
- }
209
-
210
- const jsFiles = fs.readdirSync(jsDir).filter(f => f.endsWith('.js'));
211
-
212
- for (const file of jsFiles) {
213
- const filePath = path.join(jsDir, file);
214
- let content = fs.readFileSync(filePath, 'utf8');
215
- const originalSize = Buffer.byteLength(content, 'utf8');
216
-
217
- // Remove console.log statements in production
218
- if (process.env.NODE_ENV === 'production') {
219
- content = content.replace(/console\.log\([^)]*\);?/g, '');
220
- content = content.replace(/console\.debug\([^)]*\);?/g, '');
221
- }
222
-
223
- // Remove comments
224
- content = content.replace(/\/\*[\s\S]*?\*\//g, ''); // Block comments
225
- content = content.replace(/\/\/.*/g, ''); // Line comments
226
-
227
- // Remove empty lines
228
- content = content.replace(/^\s*[\r\n]/gm, '');
229
-
230
- const optimizedSize = Buffer.byteLength(content, 'utf8');
231
-
232
- // Write optimized version
233
- fs.writeFileSync(filePath, content, 'utf8');
234
-
235
- this.stats.bytesOriginal += originalSize;
236
- this.stats.bytesOptimized += optimizedSize;
237
- }
238
- }
239
-
240
- /**
241
- * Optimize bundle size
242
- */
243
- async optimizeBundle() {
244
- // Analyze and report bundle sizes
245
- const compiledDir = this.outputDir;
246
-
247
- if (!fs.existsSync(compiledDir)) {
248
- return;
249
- }
250
-
251
- const files = fs.readdirSync(compiledDir);
252
- const bundles = [];
253
-
254
- for (const file of files) {
255
- const filePath = path.join(compiledDir, file);
256
- const stats = fs.statSync(filePath);
257
-
258
- if (stats.isFile() && file.endsWith('.js')) {
259
- bundles.push({
260
- name: file,
261
- size: stats.size,
262
- gzipSize: this.estimateGzipSize(stats.size)
263
- });
264
- }
265
- }
266
-
267
- // Sort by size
268
- bundles.sort((a, b) => b.size - a.size);
269
-
270
- // Log largest bundles
271
- const topBundles = bundles.slice(0, 5);
272
- for (const bundle of topBundles) {
273
- logger.info({
274
- code: 'MC_PERF_BUNDLE_SIZE',
275
- message: `Bundle: ${bundle.name}`,
276
- size: `${(bundle.size / 1024).toFixed(2)} KB`,
277
- gzipSize: `${(bundle.gzipSize / 1024).toFixed(2)} KB`
278
- });
279
- }
280
-
281
- return bundles;
282
- }
283
-
284
- /**
285
- * Estimate gzip size (approximation: ~30% of original)
286
- */
287
- estimateGzipSize(size) {
288
- return Math.round(size * 0.3);
289
- }
290
-
291
- /**
292
- * Find files recursively
293
- */
294
- findFiles(dir, extensions) {
295
- const files = [];
296
-
297
- if (!fs.existsSync(dir)) {
298
- return files;
299
- }
300
-
301
- const items = fs.readdirSync(dir);
302
-
303
- for (const item of items) {
304
- const fullPath = path.join(dir, item);
305
- const stat = fs.statSync(fullPath);
306
-
307
- if (stat.isDirectory()) {
308
- files.push(...this.findFiles(fullPath, extensions));
309
- } else if (extensions.some(ext => item.endsWith(ext))) {
310
- files.push(fullPath);
311
- }
312
- }
313
-
314
- return files;
315
- }
316
-
317
- /**
318
- * Log optimization results
319
- */
320
- logOptimizationResults() {
321
- const savingsPercent = this.stats.bytesOriginal > 0
322
- ? ((1 - this.stats.bytesOptimized / this.stats.bytesOriginal) * 100).toFixed(1)
323
- : 0;
324
-
325
- logger.info({
326
- code: 'MC_PERF_BUILD_COMPLETE',
327
- message: 'Build optimization complete',
328
- context: {
329
- filesProcessed: this.stats.filesProcessed,
330
- originalSize: `${(this.stats.bytesOriginal / 1024).toFixed(2)} KB`,
331
- optimizedSize: `${(this.stats.bytesOptimized / 1024).toFixed(2)} KB`,
332
- savings: `${savingsPercent}%`,
333
- timeTaken: `${this.stats.timeTaken}ms`,
334
- componentsFound: this.stats.componentsFound,
335
- componentsUsed: this.stats.componentsUsed,
336
- componentsRemoved: this.stats.componentsRemoved
337
- }
338
- });
339
-
340
- // Print summary
341
- console.log('\n═══════════════════════════════════════════════════');
342
- console.log('🚀 MasterController Build Optimization Complete');
343
- console.log('═══════════════════════════════════════════════════');
344
- console.log(`Files Processed: ${this.stats.filesProcessed}`);
345
- console.log(`Original Size: ${(this.stats.bytesOriginal / 1024).toFixed(2)} KB`);
346
- console.log(`Optimized Size: ${(this.stats.bytesOptimized / 1024).toFixed(2)} KB`);
347
- console.log(`Savings: ${savingsPercent}%`);
348
- console.log(`Time Taken: ${this.stats.timeTaken}ms`);
349
- console.log(`Components Found: ${this.stats.componentsFound}`);
350
- console.log(`Components Used: ${this.stats.componentsUsed}`);
351
- console.log(`Unused Components: ${this.stats.componentsRemoved}`);
352
- console.log('═══════════════════════════════════════════════════\n');
353
- }
354
- }
355
-
356
- // CLI usage
357
- if (require.main === module) {
358
- const optimizer = new MasterBuildOptimizer({
359
- rootDir: process.cwd(),
360
- minify: true,
361
- treeShake: true,
362
- deadCodeElimination: true
363
- });
364
-
365
- optimizer.optimize()
366
- .then(stats => {
367
- console.log('✅ Build optimization successful');
368
- process.exit(0);
369
- })
370
- .catch(error => {
371
- console.error('❌ Build optimization failed:', error.message);
372
- process.exit(1);
373
- });
374
- }
375
-
376
- module.exports = { MasterBuildOptimizer };