UNPKG

lwc-generator-cli

Version:

AI-powered Lightning Web Component generator with interactive web UI

203 lines (166 loc) 5.04 kB
const express = require('express'); const path = require('path'); const fs = require('fs').promises; const open = require('open'); const archiver = require('archiver'); async function startServer(options) { const { port, files, componentName, outputDir } = options; const app = express(); app.use(express.json()); app.use(express.static(path.join(__dirname, '../public'))); // Serve Monaco Editor from CDN in HTML // API endpoint to get file tree app.get('/api/files', (req, res) => { const tree = buildFileTree(files); res.json({ componentName, tree, files: files.map(f => ({ name: f.name, type: f.type, size: f.size, relativePath: f.relativePath })) }); }); // API endpoint to get file content app.get('/api/file/:path(*)', async (req, res) => { try { const filePath = decodeURIComponent(req.params.path); const file = files.find(f => f.relativePath === filePath); if (!file) { return res.status(404).json({ error: 'File not found' }); } res.json({ name: file.name, type: file.type, content: file.content, size: file.size }); } catch (error) { res.status(500).json({ error: error.message }); } }); // API endpoint to update file content app.post('/api/file/:path(*)', async (req, res) => { try { const filePath = decodeURIComponent(req.params.path); const file = files.find(f => f.relativePath === filePath); if (!file) { return res.status(404).json({ error: 'File not found' }); } file.content = req.body.content; await fs.writeFile(file.path, req.body.content, 'utf-8'); res.json({ success: true }); } catch (error) { res.status(500).json({ error: error.message }); } }); // API endpoint to download single file app.get('/api/download/:path(*)', async (req, res) => { try { const filePath = decodeURIComponent(req.params.path); const file = files.find(f => f.relativePath === filePath); if (!file) { return res.status(404).json({ error: 'File not found' }); } res.setHeader('Content-Type', 'application/octet-stream'); res.setHeader('Content-Disposition', `attachment; filename="${file.name}"`); res.send(file.content); } catch (error) { res.status(500).json({ error: error.message }); } }); // API endpoint to download all files as ZIP app.get('/api/download-zip', (req, res) => { res.setHeader('Content-Type', 'application/zip'); res.setHeader('Content-Disposition', `attachment; filename="${componentName}.zip"`); const archive = archiver('zip', { zlib: { level: 9 } }); archive.on('error', (err) => { res.status(500).json({ error: err.message }); }); archive.pipe(res); // Add files to archive files.forEach(file => { archive.append(file.content, { name: `${componentName}/${file.relativePath}` }); }); archive.finalize(); }); const server = app.listen(port, () => { // Open browser open(`http://localhost:${port}`); }); return server; } function buildFileTree(files) { const tree = { name: 'force-app', type: 'folder', children: [] }; // Create the nested structure const mainFolder = { name: 'main', type: 'folder', children: [] }; const defaultFolder = { name: 'default', type: 'folder', children: [] }; // Separate LWC files and Apex files const lwcFiles = files.filter(f => f.relativePath.includes('/lwc/')); const apexFiles = files.filter(f => f.relativePath.includes('/classes/')); // Add LWC folder if there are LWC files if (lwcFiles.length > 0) { const lwcFolder = { name: 'lwc', type: 'folder', children: [] }; // Group LWC files by component name const componentName = lwcFiles[0].relativePath.split('/lwc/')[1].split('/')[0]; const componentFolder = { name: componentName, type: 'folder', children: [] }; lwcFiles.forEach(file => { const fileName = file.name; componentFolder.children.push({ name: fileName, type: 'file', fileType: file.type, size: file.size, path: file.relativePath }); }); lwcFolder.children.push(componentFolder); defaultFolder.children.push(lwcFolder); } // Add classes folder if there are apex files if (apexFiles.length > 0) { const classesFolder = { name: 'classes', type: 'folder', children: [] }; apexFiles.forEach(file => { classesFolder.children.push({ name: file.name, type: 'file', fileType: file.type, size: file.size, path: file.relativePath }); }); defaultFolder.children.push(classesFolder); } mainFolder.children.push(defaultFolder); tree.children.push(mainFolder); return tree; } module.exports = { startServer };