UNPKG

lwc-linter

Version:

A comprehensive CLI tool for linting Lightning Web Components v8.0.0+ with modern LWC patterns, decorators, lifecycle hooks, and Salesforce platform integration

204 lines 9.09 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.DevServer = void 0; const express_1 = __importDefault(require("express")); const path = __importStar(require("path")); const fs = __importStar(require("fs-extra")); const chalk_1 = __importDefault(require("chalk")); const compression_1 = __importDefault(require("compression")); const linter_1 = require("./linter"); const output_formatter_1 = require("./output-formatter"); class DevServer { constructor(config, targetPath, port = 3000) { this.currentResults = []; this.app = (0, express_1.default)(); this.port = port; this.config = config; this.targetPath = targetPath; this.reportPath = path.resolve('lwc-linter-live-report.html'); this.setupServer(); } setupServer() { // Enable gzip compression for faster loading this.app.use((0, compression_1.default)({ level: 9, // Maximum compression threshold: 1024, // Compress files larger than 1KB filter: (req, res) => { // Compress everything except already compressed formats const contentType = res.getHeader('Content-Type'); if (typeof contentType === 'string') { return !contentType.includes('image/') && !contentType.includes('video/') && !contentType.includes('audio/'); } return true; } })); // Enable CORS and proper headers for all routes this.app.use((req, res, next) => { res.header('Access-Control-Allow-Origin', '*'); res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS'); res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept'); res.header('Cache-Control', 'no-cache, no-store, must-revalidate'); res.header('Pragma', 'no-cache'); res.header('Expires', '0'); res.header('Vary', 'Accept-Encoding'); // Enable compression hint next(); }); // Serve static files from current directory with optimized caching this.app.use('/static', express_1.default.static('.', { setHeaders: (res, path) => { // Cache static assets for better performance if (path.endsWith('.js') || path.endsWith('.css')) { res.header('Cache-Control', 'public, max-age=3600'); // 1 hour cache } else { res.header('Cache-Control', 'no-cache, no-store, must-revalidate'); } res.header('Vary', 'Accept-Encoding'); // Enable compression hint } })); // API endpoint to get latest lint results (for manual refresh) this.app.get('/api/lint-results', async (req, res) => { try { const linter = new linter_1.LWCLinter(this.config); const results = await linter.lintDirectory(this.targetPath); const response = { timestamp: new Date().toISOString(), results: results.map(result => ({ filePath: result.filePath, issueCount: result.issues.length, fixedCount: result.fixedCount || 0, issues: result.issues })) }; this.currentResults = response.results; res.header('Content-Type', 'application/json'); res.json(response); } catch (error) { console.error('API Error:', error); res.status(500).json({ error: error instanceof Error ? error.message : 'Unknown error' }); } }); // JavaScript error logging endpoint this.app.post('/api/log-error', express_1.default.json(), (req, res) => { const { message, line, column, error, stack, userAgent } = req.body; console.error(chalk_1.default.red('🚨 BROWSER JAVASCRIPT ERROR:')); console.error(chalk_1.default.red(` Message: ${message}`)); if (line) console.error(chalk_1.default.red(` Line: ${line}, Column: ${column}`)); if (error) console.error(chalk_1.default.red(` Error: ${error}`)); if (stack) console.error(chalk_1.default.red(` Stack: ${stack}`)); console.error(chalk_1.default.gray(` User Agent: ${userAgent}`)); console.error(chalk_1.default.red('🔄 Suggestion: Check the browser console and fix the JavaScript syntax')); res.status(200).json({ status: 'logged' }); }); // Main dashboard route this.app.get('/', async (req, res) => { await this.generateLiveReport(); res.setHeader('Cache-Control', 'no-cache, no-store, must-revalidate'); res.setHeader('Pragma', 'no-cache'); res.setHeader('Expires', '0'); res.sendFile(this.reportPath); }); // Health check this.app.get('/health', (req, res) => { res.json({ status: 'ok', timestamp: new Date().toISOString(), targetPath: this.targetPath, port: this.port }); }); // Debug endpoint this.app.get('/debug', (req, res) => { res.json({ config: this.config, targetPath: this.targetPath, port: this.port, currentResultsCount: this.currentResults.length, reportPath: this.reportPath }); }); } async generateLiveReport() { try { const linter = new linter_1.LWCLinter(this.config); const results = await linter.lintDirectory(this.targetPath); const formatter = new output_formatter_1.OutputFormatter('html'); const htmlContent = await formatter.formatWithServer(results, this.port); await fs.writeFile(this.reportPath, htmlContent); this.currentResults = results; } catch (error) { console.error('Failed to generate live report:', error); } } async start() { return new Promise((resolve, reject) => { this.server = this.app.listen(this.port, () => { console.log(chalk_1.default.green(`🚀 LWC Linter Dev Server started!`)); console.log(chalk_1.default.blue(`📊 Live Dashboard: http://localhost:${this.port}`)); console.log(chalk_1.default.green(`📁 Watching: ${this.targetPath}`)); console.log(chalk_1.default.yellow(`🔧 Debug info: http://localhost:${this.port}/debug`)); console.log(chalk_1.default.gray(`💡 Press Ctrl+C to stop the server`)); resolve(); }).on('error', (err) => { if (err.code === 'EADDRINUSE') { this.port++; this.start().then(resolve).catch(reject); } else { reject(err); } }); }); } stop() { if (this.server) { this.server.close(); console.log(chalk_1.default.yellow('🛑 Server stopped')); } } } exports.DevServer = DevServer; //# sourceMappingURL=dev-server.js.map