import { BlockDefinition } from '../../types/blocks'; export const NODEJS_BLOCKS: BlockDefinition[] = [ // ============================================================ // 📁 FILE SYSTEM — "read and write files" // ============================================================ { id: 'node_fs_read', type: 'node_fs', label: 'read file', category: 'node_fs', description: 'Read all the text from a file', framework: 'nodejs', shape: 'reporter', color: '#22c55e', icon: '📖', inputs: [], outputs: [{ id: 'content', label: '', type: 'string', position: 'right' }], config: [ { id: 'path', label: 'file path', type: 'text', default: './data.json' }, { id: 'encoding', label: 'encoding', type: 'select', default: 'utf8', options: [ { label: 'utf8', value: 'utf8' }, { label: 'ascii', value: 'ascii' }, { label: 'base64', value: 'base64' }, { label: 'hex', value: 'hex' }, ]}, ], compile: (cfg) => `fs.readFileSync('${cfg.path || './data.json'}', '${cfg.encoding || 'utf8'}')`, }, { id: 'node_fs_read_async', type: 'node_fs', label: 'read file (async)', category: 'node_fs', description: 'Read a file without blocking (use await)', framework: 'nodejs', shape: 'reporter', color: '#22c55e', icon: '📖', inputs: [], outputs: [{ id: 'content', label: '', type: 'string', position: 'right' }], config: [ { id: 'path', label: 'file path', type: 'text', default: './data.json' }, ], compile: (cfg) => `await fs.promises.readFile('${cfg.path || './data.json'}', 'utf8')`, }, { id: 'node_fs_write', type: 'node_fs', label: 'write to file', category: 'node_fs', description: 'Write text to a file', framework: 'nodejs', shape: 'stack', color: '#22c55e', icon: '📝', inputs: [], outputs: [], config: [ { id: 'path', label: 'file path', type: 'text', default: './output.txt' }, { id: 'data', label: 'text to write', type: 'textarea', default: 'Hello, Node.js!' }, ], compile: (cfg) => `fs.writeFileSync('${cfg.path || './output.txt'}', \`${cfg.data || ''}\`, 'utf8');`, }, { id: 'node_fs_write_async', type: 'node_fs', label: 'write to file (async)', category: 'node_fs', description: 'Write text to a file without blocking', framework: 'nodejs', shape: 'stack', color: '#22c55e', icon: '📝', inputs: [], outputs: [], config: [ { id: 'path', label: 'file path', type: 'text', default: './output.txt' }, { id: 'data', label: 'text to write', type: 'textarea', default: 'Hello, Node.js!' }, ], compile: (cfg) => `await fs.promises.writeFile('${cfg.path || './output.txt'}', \`${cfg.data || ''}\`, 'utf8');`, }, { id: 'node_fs_append', type: 'node_fs', label: 'add text to file', category: 'node_fs', description: 'Add more text to the end of a file', framework: 'nodejs', shape: 'stack', color: '#22c55e', icon: '➕', inputs: [], outputs: [], config: [ { id: 'path', label: 'file path', type: 'text', default: './log.txt' }, { id: 'data', label: 'text to add', type: 'textarea', default: 'New log entry\n' }, ], compile: (cfg) => `fs.appendFileSync('${cfg.path || './log.txt'}', \`${cfg.data || ''}\`);`, }, { id: 'node_fs_delete', type: 'node_fs', label: 'delete file', category: 'node_fs', description: 'Delete a file from the disk', framework: 'nodejs', shape: 'stack', color: '#22c55e', icon: '🗑', inputs: [], outputs: [], config: [ { id: 'path', label: 'file path', type: 'text', default: './old.txt' }, ], compile: (cfg) => `fs.unlinkSync('${cfg.path || './old.txt'}');`, }, { id: 'node_fs_exists', type: 'node_fs', label: 'file exists?', category: 'node_fs', description: 'Check if a file exists', framework: 'nodejs', shape: 'boolean', color: '#22c55e', icon: '❓', inputs: [], outputs: [{ id: 'exists', label: '', type: 'boolean', position: 'right' }], config: [ { id: 'path', label: 'path', type: 'text', default: './data.json' }, ], compile: (cfg) => `fs.existsSync('${cfg.path || './data.json'}')`, }, { id: 'node_fs_mkdir', type: 'node_fs', label: 'make folder', category: 'node_fs', description: 'Create a new folder (directory)', framework: 'nodejs', shape: 'stack', color: '#22c55e', icon: '📁', inputs: [], outputs: [], config: [ { id: 'path', label: 'folder path', type: 'text', default: './new-folder' }, ], compile: (cfg) => `fs.mkdirSync('${cfg.path || './new-folder'}', { recursive: true });`, }, { id: 'node_fs_readdir', type: 'node_fs', label: 'list files in folder', category: 'node_fs', description: 'Get a list of all files and folders in a directory', framework: 'nodejs', shape: 'reporter', color: '#22c55e', icon: '📂', inputs: [], outputs: [{ id: 'files', label: '', type: 'array', position: 'right' }], config: [ { id: 'path', label: 'folder path', type: 'text', default: './' }, ], compile: (cfg) => `fs.readdirSync('${cfg.path || './'}')`, }, { id: 'node_fs_rename', type: 'node_fs', label: 'rename file or folder', category: 'node_fs', description: 'Rename or move a file or folder', framework: 'nodejs', shape: 'stack', color: '#22c55e', icon: '✏', inputs: [], outputs: [], config: [ { id: 'oldPath', label: 'old name', type: 'text', default: './old.txt' }, { id: 'newPath', label: 'new name', type: 'text', default: './new.txt' }, ], compile: (cfg) => `fs.renameSync('${cfg.oldPath || './old.txt'}', '${cfg.newPath || './new.txt'}');`, }, { id: 'node_fs_copy', type: 'node_fs', label: 'copy file', category: 'node_fs', description: 'Make a copy of a file', framework: 'nodejs', shape: 'stack', color: '#22c55e', icon: '📋', inputs: [], outputs: [], config: [ { id: 'src', label: 'source file', type: 'text', default: './source.txt' }, { id: 'dest', label: 'destination file', type: 'text', default: './copy.txt' }, ], compile: (cfg) => `fs.copyFileSync('${cfg.src || './source.txt'}', '${cfg.dest || './copy.txt'}');`, }, { id: 'node_fs_stats', type: 'node_fs', label: 'file info (stats)', category: 'node_fs', description: 'Get information about a file (size, created date, etc.)', framework: 'nodejs', shape: 'reporter', color: '#22c55e', icon: '📊', inputs: [], outputs: [{ id: 'stats', label: '', type: 'object', position: 'right' }], config: [ { id: 'path', label: 'path', type: 'text', default: './file.txt' }, ], compile: (cfg) => `fs.statSync('${cfg.path || './file.txt'}')`, }, // ============================================================ // 🌍 HTTP — "create a web server" // ============================================================ { id: 'node_http_server', type: 'node_http', label: 'start HTTP server', category: 'node_http', description: 'Create a basic web server that responds to requests', framework: 'nodejs', shape: 'stack', color: '#f97316', icon: '🌐', inputs: [], outputs: [], config: [ { id: 'port', label: 'port number', type: 'number', default: 3000 }, { id: 'requestHandler', label: 'response code', type: 'textarea', default: 'res.writeHead(200, { "Content-Type": "text/plain" });\nres.end("Hello World\\n");' }, ], compile: (cfg) => `http.createServer((req, res) => {\n ${cfg.requestHandler || 'res.writeHead(200, { "Content-Type": "text/plain" }); res.end("Hello World");'}\n}).listen(${cfg.port ?? 3000}, () => {\n console.log('Server running on port ${cfg.port ?? 3000}');\n});`, }, { id: 'node_http_get_url', type: 'node_http', label: 'fetch URL (http get)', category: 'node_http', description: 'Make an HTTP GET request to a URL', framework: 'nodejs', shape: 'stack', color: '#f97316', icon: '📡', inputs: [], outputs: [], config: [ { id: 'url', label: 'URL', type: 'text', default: 'http://example.com' }, { id: 'resultVar', label: 'save result in', type: 'text', default: 'data' }, ], compile: (cfg) => `const response = await fetch('${cfg.url || 'http://example.com'}');\nconst ${cfg.resultVar || 'data'} = await response.text();`, }, // ============================================================ // 🚀 EXPRESS — "make a web app" // ============================================================ { id: 'node_express_app', type: 'node_express', label: 'start Express app', category: 'node_express', description: 'Create an Express web application', framework: 'nodejs', shape: 'stack', color: '#8B5CF6', icon: '🚀', inputs: [], outputs: [], config: [ { id: 'port', label: 'port number', type: 'number', default: 3000 }, { id: 'useJSON', label: 'use JSON body parser?', type: 'boolean', default: true }, { id: 'routesText', label: 'route code', type: 'textarea', default: 'app.get("/", (req, res) => {\n res.json({ message: "Hello World!" });\n});' }, ], compile: (cfg) => { const lines = [`const express = require('express');`]; lines.push(`const app = express();`); lines.push(``); if (cfg.useJSON) lines.push(`app.use(express.json());`); lines.push(``); lines.push(`${cfg.routesText || 'app.get("/", (req, res) => res.json({ message: "Hello World!" }));'}`); lines.push(``); lines.push(`app.listen(${cfg.port ?? 3000}, () => {`); lines.push(` console.log('Server running on port ${cfg.port ?? 3000}');`); lines.push(`});`); return lines.join('\n'); }, }, { id: 'node_express_route', type: 'node_express', label: 'handle route (GET/POST)', category: 'node_express', description: 'Handle requests to a specific URL path', framework: 'nodejs', shape: 'stack', color: '#8B5CF6', icon: '🛣', inputs: [], outputs: [], config: [ { id: 'method', label: 'method', type: 'select', default: 'get', options: [ { label: 'GET', value: 'get' }, { label: 'POST', value: 'post' }, { label: 'PUT', value: 'put' }, { label: 'DELETE', value: 'delete' }, { label: 'PATCH', value: 'patch' }, ]}, { id: 'path', label: 'URL path', type: 'text', default: '/api/items' }, { id: 'handler', label: 'response code', type: 'textarea', default: 'res.json({ items: [] });' }, ], compile: (cfg) => `app.${cfg.method || 'get'}('${cfg.path || '/'}', (req, res) => {\n ${cfg.handler || 'res.json({});'}\n});`, }, { id: 'node_express_static', type: 'node_express', label: 'serve static files', category: 'node_express', description: 'Serve files from a folder (like HTML, CSS, images)', framework: 'nodejs', shape: 'stack', color: '#8B5CF6', icon: '📂', inputs: [], outputs: [], config: [ { id: 'directory', label: 'folder name', type: 'text', default: 'public' }, { id: 'mountPath', label: 'URL path', type: 'text', default: '/' }, ], compile: (cfg) => `app.use('${cfg.mountPath || '/'}', express.static(path.join(__dirname, '${cfg.directory || 'public'}')));`, }, { id: 'node_express_error', type: 'node_express', label: 'error handler', category: 'node_express', description: 'Catch errors and send a response instead of crashing', framework: 'nodejs', shape: 'stack', color: '#8B5CF6', icon: '⚠', inputs: [], outputs: [], config: [ { id: 'handlerCode', label: 'error handler code', type: 'textarea', default: 'console.error(err.stack);\nres.status(500).json({ error: "Something went wrong!" });' }, ], compile: (cfg) => `app.use((err, req, res, next) => {\n ${cfg.handlerCode || 'console.error(err.stack); res.status(500).json({ error: "Error" });'}\n});`, }, { id: 'node_express_auth_middleware', type: 'node_express', label: 'auth middleware', category: 'node_express', description: 'Check if a user is logged in before letting them through', framework: 'nodejs', shape: 'stack', color: '#8B5CF6', icon: '🔒', inputs: [], outputs: [], config: [ { id: 'headerName', label: 'header to check', type: 'text', default: 'Authorization' }, { id: 'secret', label: 'JWT secret', type: 'text', default: 'process.env.JWT_SECRET' }, ], compile: (cfg) => `const authMiddleware = (req, res, next) => {\n const token = req.header('${cfg.headerName || 'Authorization'}')?.replace('Bearer ', '');\n if (!token) return res.status(401).json({ error: "Unauthorized" });\n try {\n const decoded = jwt.verify(token, ${cfg.secret || 'process.env.JWT_SECRET'});\n req.user = decoded;\n next();\n } catch (err) {\n res.status(401).json({ error: "Invalid token" });\n }\n};`, }, // ============================================================ // 🗄 DATABASE — "save and load data" // ============================================================ { id: 'node_db_sqlite', type: 'node_db', label: 'run SQL on database', category: 'node_db', description: 'Run a SQL query on a database (like SELECT, INSERT, UPDATE, DELETE)', framework: 'nodejs', shape: 'reporter', color: '#F59E0B', icon: '🗄', inputs: [], outputs: [{ id: 'result', label: '', type: 'any', position: 'right' }], config: [ { id: 'dbVar', label: 'database variable', type: 'text', default: 'db' }, { id: 'query', label: 'SQL query', type: 'textarea', default: 'SELECT * FROM users' }, ], compile: (cfg) => `${cfg.dbVar || 'db'}.prepare(\`${cfg.query || 'SELECT 1'}\`).all()`, }, { id: 'node_db_sqlite_run', type: 'node_db', label: 'run SQL (insert/update)', category: 'node_db', description: 'Run a SQL command that changes data (INSERT, UPDATE, DELETE)', framework: 'nodejs', shape: 'stack', color: '#F59E0B', icon: '🗄', inputs: [], outputs: [], config: [ { id: 'dbVar', label: 'database variable', type: 'text', default: 'db' }, { id: 'query', label: 'SQL command', type: 'textarea', default: 'INSERT INTO users (name) VALUES ("John")' }, ], compile: (cfg) => `${cfg.dbVar || 'db'}.prepare(\`${cfg.query || ''}\`).run();`, }, { id: 'node_db_mongodb_find', type: 'node_db', label: 'find in MongoDB', category: 'node_db', description: 'Find documents in a MongoDB collection', framework: 'nodejs', shape: 'reporter', color: '#F59E0B', icon: '🍃', inputs: [], outputs: [{ id: 'result', label: '', type: 'any', position: 'right' }], config: [ { id: 'collection', label: 'collection name', type: 'text', default: 'users' }, { id: 'filter', label: 'filter (JSON)', type: 'text', default: '{}' }, ], compile: (cfg) => `db.collection('${cfg.collection || 'users'}').find(${cfg.filter || '{}'}).toArray()`, }, { id: 'node_db_mongodb_insert', type: 'node_db', label: 'insert into MongoDB', category: 'node_db', description: 'Add a new document to a MongoDB collection', framework: 'nodejs', shape: 'stack', color: '#F59E0B', icon: '🍃', inputs: [], outputs: [], config: [ { id: 'collection', label: 'collection name', type: 'text', default: 'users' }, { id: 'document', label: 'document (JSON)', type: 'text', default: '{ name: "John", age: 30 }' }, ], compile: (cfg) => `await db.collection('${cfg.collection || 'users'}').insertOne(${cfg.document || '{}'});`, }, // ============================================================ // 📦 MODULES — "import and export" // ============================================================ { id: 'node_require', type: 'node_modules', label: 'import module (require)', category: 'node_modules', description: 'Load a Node.js module', framework: 'nodejs', shape: 'stack', color: '#6366f1', icon: '📦', inputs: [], outputs: [], config: [ { id: 'variable', label: 'variable name', type: 'text', default: 'express' }, { id: 'module', label: 'module name', type: 'text', default: 'express' }, ], compile: (cfg) => `const ${cfg.variable || 'express'} = require('${cfg.module || 'express'}');`, }, { id: 'node_import_esm', type: 'node_modules', label: 'import (ES module)', category: 'node_modules', description: 'Import using ES module syntax', framework: 'nodejs', shape: 'stack', color: '#6366f1', icon: '📦', inputs: [], outputs: [], config: [ { id: 'names', label: 'import names', type: 'text', default: '{ readFile }' }, { id: 'module', label: 'from module', type: 'text', default: 'fs/promises' }, ], compile: (cfg) => `import ${cfg.names || '{ readFile }'} from '${cfg.module || 'fs/promises'}';`, }, { id: 'node_export_single', type: 'node_modules', label: 'export (module.exports)', category: 'node_modules', description: 'Export a value so other files can use it', framework: 'nodejs', shape: 'stack', color: '#6366f1', icon: '📤', inputs: [], outputs: [], config: [ { id: 'value', label: 'value to export', type: 'textarea', default: '() => { console.log("Hello"); }' }, ], compile: (cfg) => `module.exports = ${cfg.value || '{}'};`, }, { id: 'node_export_named', type: 'node_modules', label: 'export named value', category: 'node_modules', description: 'Export a named value so other files can import it', framework: 'nodejs', shape: 'stack', color: '#6366f1', icon: '📤', inputs: [], outputs: [], config: [ { id: 'name', label: 'export name', type: 'text', default: 'myFunction' }, { id: 'value', label: 'value', type: 'textarea', default: '() => { console.log("Hello"); }' }, ], compile: (cfg) => `exports.${cfg.name || 'myFunction'} = ${cfg.value || '() => {}'};`, }, // ============================================================ // 🛠 UTILITIES — "helpful tools" // ============================================================ { id: 'node_path_join', type: 'node_utils', label: 'join path parts', category: 'node_utils', description: 'Join parts of a path together (handles slashes for you)', framework: 'nodejs', shape: 'reporter', color: '#6366f1', icon: '📎', inputs: [], outputs: [{ id: 'path', label: '', type: 'string', position: 'right' }], config: [ { id: 'segments', label: 'parts (comma separated)', type: 'text', default: '__dirname, "data", "file.json"' }, ], compile: (cfg) => `path.join(${cfg.segments || '__dirname, "data", "file.json"'})`, }, { id: 'node_path_dirname', type: 'node_utils', label: 'folder of path', category: 'node_utils', description: 'Get the folder/directory part of a path', framework: 'nodejs', shape: 'reporter', color: '#6366f1', icon: '📁', inputs: [], outputs: [{ id: 'result', label: '', type: 'string', position: 'right' }], config: [ { id: 'path', label: 'path', type: 'text', default: '/path/to/file.txt' }, ], compile: (cfg) => `path.dirname('${cfg.path || '/path/to/file.txt'}')`, }, { id: 'node_path_basename', type: 'node_utils', label: 'file name from path', category: 'node_utils', description: 'Get the file name from a path', framework: 'nodejs', shape: 'reporter', color: '#6366f1', icon: '📄', inputs: [], outputs: [{ id: 'name', label: '', type: 'string', position: 'right' }], config: [ { id: 'path', label: 'path', type: 'text', default: '/path/to/file.txt' }, ], compile: (cfg) => `path.basename('${cfg.path || '/path/to/file.txt'}')`, }, // ============================================================ // 💻 OS & PROCESS — "computer info" // ============================================================ { id: 'node_os_info', type: 'node_utils', label: 'get OS info', category: 'node_utils', description: 'Get information about the operating system', framework: 'nodejs', shape: 'reporter', color: '#6366f1', icon: '💻', inputs: [], outputs: [{ id: 'info', label: '', type: 'any', position: 'right' }], config: [ { id: 'infoType', label: 'info type', type: 'select', default: 'platform', options: [ { label: 'OS name (win32/linux/darwin)', value: 'platform' }, { label: 'CPU architecture', value: 'arch' }, { label: 'CPU info', value: 'cpus' }, { label: 'total memory', value: 'totalmem' }, { label: 'free memory', value: 'freemem' }, { label: 'home folder', value: 'homedir' }, { label: 'computer name', value: 'hostname' }, { label: 'system uptime (seconds)', value: 'uptime' }, ]}, ], compile: (cfg) => `os.${cfg.infoType || 'platform'}()`, }, { id: 'node_env_var', type: 'node_utils', label: 'get environment variable', category: 'node_utils', description: 'Read a value set in the environment (like a secret or setting)', framework: 'nodejs', shape: 'reporter', color: '#6366f1', icon: '🔑', inputs: [], outputs: [{ id: 'value', label: '', type: 'string', position: 'right' }], config: [ { id: 'name', label: 'variable name', type: 'text', default: 'PORT' }, { id: 'default', label: 'fallback if not set', type: 'text', default: '3000' }, ], compile: (cfg) => `process.env.${cfg.name || 'PORT'} || '${cfg.default || ''}'`, }, { id: 'node_process_args', type: 'node_utils', label: 'command line arguments', category: 'node_utils', description: 'Get the arguments passed when the program was started', framework: 'nodejs', shape: 'reporter', color: '#6366f1', icon: '⌨', inputs: [], outputs: [{ id: 'args', label: '', type: 'array', position: 'right' }], config: [ { id: 'all', label: 'return all args?', type: 'boolean', default: true }, { id: 'index', label: 'or get one by position', type: 'number', default: 2 }, ], compile: (cfg) => cfg.all ? 'process.argv.slice(2)' : `process.argv[${cfg.index ?? 2}]`, }, { id: 'node_process_cwd', type: 'node_utils', label: 'current working folder', category: 'node_utils', description: 'Get the folder where the script is running', framework: 'nodejs', shape: 'reporter', color: '#6366f1', icon: '📂', inputs: [], outputs: [{ id: 'path', label: '', type: 'string', position: 'right' }], config: [], compile: () => 'process.cwd()', }, { id: 'node_process_exit', type: 'node_utils', label: 'exit program', category: 'node_utils', description: 'Stop the program with an exit code (0 = success)', framework: 'nodejs', shape: 'cap', color: '#6366f1', icon: '⏹', inputs: [], outputs: [], config: [ { id: 'code', label: 'exit code', type: 'number', default: 0 }, ], compile: (cfg) => `process.exit(${cfg.code ?? 0});`, }, // ============================================================ // ⏳ ASYNC & STREAMS — "handle large data" // ============================================================ { id: 'node_stream_read', type: 'node_async', label: 'read stream from file', category: 'node_async', description: 'Create a stream to read a file bit by bit (good for large files)', framework: 'nodejs', shape: 'reporter', color: '#EF4444', icon: '📤', inputs: [], outputs: [{ id: 'stream', label: '', type: 'object', position: 'right' }], config: [ { id: 'path', label: 'file path', type: 'text', default: './large-file.txt' }, ], compile: (cfg) => `fs.createReadStream('${cfg.path || './large-file.txt'}', 'utf8')`, }, { id: 'node_stream_write', type: 'node_async', label: 'write stream to file', category: 'node_async', description: 'Create a stream to write data to a file bit by bit', framework: 'nodejs', shape: 'reporter', color: '#EF4444', icon: '📥', inputs: [], outputs: [{ id: 'stream', label: '', type: 'object', position: 'right' }], config: [ { id: 'path', label: 'file path', type: 'text', default: './output.txt' }, ], compile: (cfg) => `fs.createWriteStream('${cfg.path || './output.txt'}')`, }, { id: 'node_stream_pipe', type: 'node_async', label: 'pipe stream A to B', category: 'node_async', description: 'Send data from one stream to another', framework: 'nodejs', shape: 'stack', color: '#EF4444', icon: '🔗', inputs: [], outputs: [], config: [ { id: 'source', label: 'source stream', type: 'text', default: 'readableStream' }, { id: 'dest', label: 'destination stream', type: 'text', default: 'writableStream' }, ], compile: (cfg) => `${cfg.source || 'readableStream'}.pipe(${cfg.dest || 'writableStream'});`, }, { id: 'node_child_exec', type: 'node_async', label: 'run command (exec)', category: 'node_async', description: 'Run a command in the terminal', framework: 'nodejs', shape: 'reporter', color: '#EF4444', icon: '⚙', inputs: [], outputs: [{ id: 'result', label: '', type: 'string', position: 'right' }], config: [ { id: 'command', label: 'command', type: 'text', default: 'ls -la' }, ], compile: (cfg) => `execSync('${cfg.command || 'ls -la'}').toString()`, }, { id: 'node_crypto_hash', type: 'node_async', label: 'create hash', category: 'node_async', description: 'Create a scrambled version of some text (like a password)', framework: 'nodejs', shape: 'reporter', color: '#EF4444', icon: '#️⃣', inputs: [], outputs: [{ id: 'hash', label: '', type: 'string', position: 'right' }], config: [ { id: 'value', label: 'text to hash', type: 'text', default: 'password123' }, { id: 'algorithm', label: 'algorithm', type: 'select', default: 'sha256', options: [ { label: 'SHA-256', value: 'sha256' }, { label: 'SHA-512', value: 'sha512' }, { label: 'MD5', value: 'md5' }, ]}, ], compile: (cfg) => `crypto.createHash('${cfg.algorithm || 'sha256'}').update('${cfg.value || ''}').digest('hex')`, }, { id: 'node_event_emitter', type: 'node_async', label: 'listen for event', category: 'node_async', description: 'Listen for an event from an EventEmitter', framework: 'nodejs', shape: 'hat', color: '#EF4444', icon: '📡', inputs: [{ id: 'handler', label: 'run', type: 'code', position: 'bottom' }], outputs: [], config: [ { id: 'emitter', label: 'emitter variable', type: 'text', default: 'emitter' }, { id: 'event', label: 'event name', type: 'text', default: 'data' }, ], compile: (cfg, inputs) => `${cfg.emitter || 'emitter'}.on('${cfg.event || 'data'}', (data) => {\n${inputs.handler || ''}\n});`, }, { id: 'node_event_emit', type: 'node_async', label: 'emit (send) event', category: 'node_async', description: 'Send an event to all listeners', framework: 'nodejs', shape: 'stack', color: '#EF4444', icon: '📡', inputs: [], outputs: [], config: [ { id: 'emitter', label: 'emitter variable', type: 'text', default: 'emitter' }, { id: 'event', label: 'event name', type: 'text', default: 'data' }, { id: 'data', label: 'data to send', type: 'text', default: '{ message: "hello" }' }, ], compile: (cfg) => `${cfg.emitter || 'emitter'}.emit('${cfg.event || 'data'}', ${cfg.data || '{}'});`, }, // ============================================================ // 🔌 WEBSOCKET — "real-time connections" // ============================================================ { id: 'node_websocket_server', type: 'node_websocket', label: 'start WebSocket server', category: 'node_websocket', description: 'Create a real-time WebSocket server', framework: 'nodejs', shape: 'stack', color: '#22d3ee', icon: '🔌', inputs: [], outputs: [], config: [ { id: 'port', label: 'port number', type: 'number', default: 8080 }, { id: 'onConnection', label: 'connection handler code', type: 'textarea', default: 'ws.on("message", (data) => {\n console.log("Received:", data.toString());\n ws.send("Echo: " + data.toString());\n});' }, ], compile: (cfg) => `const WebSocket = require('ws');\n\nconst wss = new WebSocket.Server({ port: ${cfg.port ?? 8080} });\n\nwss.on('connection', (ws, req) => {\n console.log('Client connected');\n ${cfg.onConnection || 'ws.on("message", (data) => ws.send("Echo: " + data.toString()));'}\n});\n\nconsole.log('WebSocket server running on port ${cfg.port ?? 8080}');`, }, // ============================================================ // 🛡 JWT AUTH — "secure tokens" // ============================================================ { id: 'node_jwt_sign', type: 'node_jwt', label: 'sign JWT token', category: 'node_jwt', description: 'Create a signed JWT token (like a digital ID card)', framework: 'nodejs', shape: 'reporter', color: '#f59e0b', icon: '🛡', inputs: [], outputs: [{ id: 'token', label: '', type: 'string', position: 'right' }], config: [ { id: 'payload', label: 'data (JSON)', type: 'text', default: '{ userId: 123 }' }, { id: 'secret', label: 'secret key', type: 'text', default: 'process.env.JWT_SECRET' }, { id: 'expiresIn', label: 'expires in', type: 'text', default: '7d' }, ], compile: (cfg) => `jwt.sign(${cfg.payload || '{}'}, ${cfg.secret || 'process.env.JWT_SECRET'}, { expiresIn: '${cfg.expiresIn || '7d'}' })`, }, { id: 'node_jwt_verify', type: 'node_jwt', label: 'verify JWT token', category: 'node_jwt', description: 'Check if a JWT token is valid and decode it', framework: 'nodejs', shape: 'reporter', color: '#f59e0b', icon: '🔓', inputs: [], outputs: [{ id: 'result', label: '', type: 'any', position: 'right' }], config: [ { id: 'token', label: 'token to check', type: 'text', default: '...' }, { id: 'secret', label: 'secret key', type: 'text', default: 'process.env.JWT_SECRET' }, ], compile: (cfg) => `jwt.verify('${cfg.token || ''}', ${cfg.secret || 'process.env.JWT_SECRET'})`, }, ];