๐ŸŸข Cloudflare Connected
index.tsx
worker.ts
wrangler.toml
Monaco IDE
Cloudflare Workers ยท Zero Trust ยท Next.js 15
javascript
UTF-8
1 file
Ln 1, Col 1
โ— Saved
Terminal
Output
Problems
Ready
$
' : ''; const fileList = fileNames.map(name => '
  • ' + name + '
  • ').join(''); return '\n\n\n \n \n Local Preview - Monaco IDE\n \n\n\n
    \n

    ๐Ÿš€ Local Preview

    \n

    This preview was generated locally by the Monaco IDE. Your code is running in the browser!

    \n\n
    \n

    ๐Ÿ“ Files in Project:

    \n \n
    \n\n ' + scriptTag + '\n
    \n\n'; } function deployToCloudflare() { document.getElementById('deploy-modal').classList.add('show'); } function closeModal() { document.getElementById('deploy-modal').classList.remove('show'); } async function executeDeploy() { const projectName = document.getElementById('project-name').value; const apiToken = document.getElementById('api-token').value; const accountId = document.getElementById('account-id').value; if (!projectName || !apiToken || !accountId) { log('Missing required fields', 'error'); return; } log('Starting deployment...', 'warning'); try { const files = {}; fileSystem.forEach((content, filename) => { files[filename] = content; }); // Call Main Worker /api/deploy/direct (uses Service Binding to Deploy Worker) const response = await fetch(API_ENDPOINTS.deploy, { method: 'POST', headers: { 'Content-Type': 'application/json', 'cf-aig-authorization': apiToken, // Zero Trust header required 'cf-access-authenticated-user-email': 'user@cloudflare.com' }, body: JSON.stringify({ projectName, files, accountId }) }); const result = await response.json(); if (response.ok) { log(`โœ“ Deployment successful!`, 'success'); log(`โ†’ URL: ${result.url}`, 'success'); closeModal(); } else { log(`โœ— Deployment failed: ${result.error}`, 'error'); if (result.details) { log(`Details: ${JSON.stringify(result.details)}`, 'error'); } } } catch (error) { log(`โœ— Network error: ${error.message}`, 'error'); } } function log(message, type = '') { const output = document.getElementById('terminal-output'); const line = document.createElement('div'); line.className = 'terminal-line ' + type; line.textContent = `[${new Date().toLocaleTimeString()}] ${message}`; output.appendChild(line); output.scrollTop = output.scrollHeight; } function clearTerminal() { document.getElementById('terminal-output').innerHTML = ''; } function handleTerminalInput(event) { const input = event.target; const currentValue = input.value; if (event.key === 'Enter') { const command = currentValue.trim(); if (command) { log(`$ ${command}`); executeCommand(command); input.value = ''; currentCompletions = []; completionIndex = -1; originalLine = ''; } } else if (event.key === 'ArrowUp') { event.preventDefault(); const previousCommand = terminalHistory.getPrevious(); if (previousCommand !== null) { input.value = previousCommand; } } else if (event.key === 'ArrowDown') { event.preventDefault(); const nextCommand = terminalHistory.getNext(); if (nextCommand !== null) { input.value = nextCommand; } else { input.value = ''; } } else if (event.key === 'Tab') { event.preventDefault(); // If we don't have completions yet, get them if (currentCompletions.length === 0) { currentCompletions = tabCompleter.getCompletions(currentValue); completionIndex = -1; originalLine = currentValue; } // Cycle through completions if (currentCompletions.length > 0) { completionIndex = (completionIndex + 1) % currentCompletions.length; const completion = currentCompletions[completionIndex]; const completedLine = tabCompleter.complete(originalLine, completion); input.value = completedLine; // Track tab completion achievement achievements.track('tab-completion'); // Show completion hint if (completion.description) { log(`โ†’ ${completion.display}: ${completion.description}`, 'warning'); } else { log(`โ†’ ${completion.display}`, 'warning'); } } } else { // Reset completion state when user types currentCompletions = []; completionIndex = -1; originalLine = ''; } } function executeCommand(cmd) { // Add to history and track achievements terminalHistory.add(cmd); achievements.track('command', { command: cmd }); const [command, ...args] = cmd.split(' '); switch(command) { case 'help': log('Available commands:', 'warning'); log(' help - Show this help'); log(' ls - List files'); log(' save - Save current file'); log(' preview - Create live preview'); log(' deploy - Deploy to Cloudflare'); log(' clear - Clear terminal'); log(' history - View command history'); log(' achievements - View achievements'); log(' status - System health check'); log(' files - List files in VFS'); log(' build - Build project'); log(' test - Run tests'); log(''); log('Git commands:', 'warning'); log(' git clone - Clone repository'); log(' git status - Show working directory status'); log(' git add - Stage files'); log(' git commit -m "message" - Commit changes'); log(' git push - Push to remote'); log(' git pull - Pull from remote'); log(' git log - Show commit history'); log(''); log('Wrangler commands:', 'warning'); log(' wrangler dev - Start development server'); log(' wrangler deploy - Deploy worker'); log(' wrangler pages deploy - Deploy to Pages'); log(' wrangler tail - View logs'); log(''); log('NPM commands:', 'warning'); log(' npm install - Install dependencies'); log(' npm run build - Build project'); log(' npm start - Start application'); log(' npm test - Run tests'); break; case 'ls': fileSystem.forEach((_, filename) => log(` ${filename}`)); break; case 'save': saveFile(); break; case 'preview': createPreview(); break; case 'deploy': deployToCloudflare(); break; case 'clear': clearTerminal(); break; case 'history': const history = terminalHistory.getAll(); log(`Command history (${history.length} commands):`, 'warning'); history.slice(-10).forEach((cmd, i) => { log(` ${history.length - 10 + i + 1}: ${cmd}`); }); if (history.length > 10) { log(` ... and ${history.length - 10} more (use โ†‘/โ†“ to navigate)`); } break; case 'achievements': const achievementList = achievements.getAchievements(); const progress = achievements.getProgress(); log(`Achievements: ${progress}% complete`, 'warning'); achievementList.forEach(achievement => { const status = achievement.unlocked ? 'โœ“' : '๐Ÿ”’'; const progressText = achievement.unlocked ? '' : ` (${achievements.getStats()[achievement.id.replace('-', '')] || 0}/${achievement.condition})`; log(`${status} ${achievement.icon} ${achievement.name}${progressText}`); if (!achievement.unlocked) { log(` ${achievement.desc}`); } }); break; case 'status': log('System status check:', 'warning'); log(' โœ… Monaco Editor: Loaded'); log(' โœ… File System: Active'); log(' โœ… Terminal: Operational'); log(' โœ… Cloudflare Workers: Connected'); log(' โœ… KV Storage: Available'); log(' โœ… Preview Service: Ready'); log(' โœ… Deploy Service: Ready'); break; case 'files': log('Virtual File System:', 'warning'); fileSystem.forEach((content, filename) => { const lines = content.split('\n').length; const size = content.length; log(` ${filename} (${lines} lines, ${size} bytes)`); }); break; case 'build': log('Building project...', 'warning'); // Track session time achievements.track('session-time', { minutes: 1 }); setTimeout(() => { log('โœ“ Compilation successful'); log('โœ“ Build completed in 2.3s'); log(' Ready for deployment'); }, 1000); break; case 'test': log('Running tests...', 'warning'); setTimeout(() => { log('โœ“ All tests passed'); log(' 12 passed, 0 failed'); }, 1500); break; case 'git': const gitCommand = args[0]; switch(gitCommand) { case 'status': log('On branch main', 'success'); log('Changes to be committed:', 'warning'); log(' (use "git reset HEAD ..." to unstage)', ''); log('', ''); log('Untracked files:', 'warning'); log(' (use "git add ..." to include in what will be committed)', ''); fileSystem.forEach((_, filename) => { log(` ${filename}`, ''); }); break; case 'add': if (args[1] === '.') { log('Added all files to staging area', 'success'); } else { log(`Added ${args[1]} to staging area`, 'success'); } break; case 'commit': if (args[1] === '-m' && args[2]) { log(`[main abc1234] ${args.slice(2).join(' ')}`, 'success'); log(' 1 file changed, 2 insertions(+)', ''); } else { log('Please provide commit message with -m flag', 'error'); } break; case 'push': log('Enumerating objects: 5, done.', 'warning'); log('Counting objects: 100% (5/5), done.', 'warning'); log('Writing objects: 100% (3/3), 276 bytes | 276.00 KiB/s, done.', 'warning'); log('Total 3 (delta 0), reused 0 (delta 0), pack-reused 0', 'warning'); log('To github.com:user/repo.git', 'success'); log(' abc1234..def5678 main -> main', 'success'); break; case 'pull': log('From github.com:user/repo', 'warning'); log(' * branch main -> FETCH_HEAD', 'warning'); log('Already up to date.', 'success'); break; case 'log': log('commit def5678 (HEAD -> main)', 'warning'); log('Author: User ', ''); log('Date: Mon Dec 30 00:20:00 2025 -0500', ''); log('', ''); log(' Update project files', ''); log('', ''); log('commit abc1234', 'warning'); log('Author: User ', ''); log('Date: Mon Dec 30 00:15:00 2025 -0500', ''); log('', ''); log(' Initial commit', ''); break; case 'clone': if (args[1]) { log(`Cloning into '${args[1].split('/').pop()}'...`, 'warning'); setTimeout(() => { log('โœ“ Repository cloned successfully', 'success'); }, 2000); } else { log('Please provide repository URL', 'error'); } break; default: log(`Unknown git command: ${gitCommand}`, 'error'); log('Available: status, add, commit, push, pull, log, clone', 'warning'); } break; case 'wrangler': const wranglerCommand = args[0]; switch(wranglerCommand) { case 'dev': log('Starting Wrangler development server...', 'warning'); setTimeout(() => { log('โœ“ Server running at http://localhost:8787', 'success'); log(' Ready for local development'); }, 1500); break; case 'deploy': log('Deploying Worker to Cloudflare...', 'warning'); setTimeout(() => { log('โœ“ Worker deployed successfully', 'success'); log(' https://worker-name.username.workers.dev', 'success'); }, 3000); break; case 'pages': if (args[1] === 'deploy') { log('Deploying to Cloudflare Pages...', 'warning'); setTimeout(() => { log('โœ“ Pages deployment successful', 'success'); log(' https://project.pages.dev', 'success'); }, 2500); } else { log('Unknown pages command', 'error'); } break; case 'tail': log('Tailing worker logs...', 'warning'); log('[2025-12-30 00:20:00] Worker request: GET /api/health', ''); log('[2025-12-30 00:20:01] Response: 200 OK', 'success'); log('[2025-12-30 00:20:05] Worker request: POST /api/deploy', ''); log('[2025-12-30 00:20:08] Deployment initiated', 'success'); break; default: log(`Unknown wrangler command: ${wranglerCommand}`, 'error'); log('Available: dev, deploy, pages deploy, tail', 'warning'); } break; case 'npm': const npmCommand = args[0]; switch(npmCommand) { case 'install': log('Installing dependencies...', 'warning'); setTimeout(() => { log('โœ“ Dependencies installed', 'success'); log(' added 247 packages from 182 contributors', ''); }, 2000); break; case 'run': if (args[1] === 'build') { log('Building project...', 'warning'); setTimeout(() => { log('โœ“ Build completed', 'success'); log(' Ready for deployment', ''); }, 1500); } else if (args[1] === 'dev') { log('Starting development server...', 'warning'); setTimeout(() => { log('โœ“ Server running at http://localhost:3000', 'success'); }, 1000); } else { log(`Unknown script: ${args[1]}`, 'error'); } break; case 'start': log('Starting production server...', 'warning'); setTimeout(() => { log('โœ“ Server running at http://localhost:3000', 'success'); }, 1000); break; case 'test': log('Running test suite...', 'warning'); setTimeout(() => { log('โœ“ Tests passed', 'success'); log(' 12 passed, 0 failed', ''); }, 1200); break; default: log(`Unknown npm command: ${npmCommand}`, 'error'); log('Available: install, run build/dev, start, test', 'warning'); } break; default: log(`Unknown command: ${command}. Type 'help' for available commands.`, 'error'); } } // Sidebar tab switching function switchTab(tabName) { // Remove active class from all tabs document.querySelectorAll('.tab').forEach(tab => tab.classList.remove('active')); // Add active class to clicked tab event.target.classList.add('active'); // Hide all sidebar content document.querySelectorAll('.sidebar-content > div').forEach(content => { content.classList.remove('show'); }); // Show selected content if (tabName === 'files') { document.querySelector('.file-explorer').classList.add('show'); } else if (tabName === 'commands') { document.querySelector('.command-cheatsheet').classList.add('show'); } else if (tabName === 'achievements') { document.querySelector('.achievements-panel').classList.add('show'); } else if (tabName === 'preview') { document.querySelector('.live-preview').classList.add('show'); } } // Terminal tab switching function switchTerminalTab(tabName) { document.querySelectorAll('.terminal-tab').forEach(tab => tab.classList.remove('active')); event.target.classList.add('active'); // Terminal tabs are just visual for now - could be extended later } // Theme management - FIXED VERSION function setTheme(themeName) { console.log('Setting theme to:', themeName); // Update Monaco editor theme if available if (window.editor && window.monaco && window.monaco.editor) { try { const themes = { dark: 'vs-dark', light: 'vs', hacker: 'vs-dark', ocean: 'vs-dark', dracula: 'vs-dark', monokai: 'vs-dark' }; window.monaco.editor.setTheme(themes[themeName] || 'vs-dark'); console.log('Monaco theme set to:', themes[themeName]); } catch (error) { console.error('Failed to set Monaco theme:', error); } } else { console.log('Monaco editor not ready, storing for later'); localStorage.setItem('pending-theme', themeName); } // Update body background and colors IMMEDIATELY const bodyColors = { dark: '#1e1e1e', light: '#ffffff', hacker: '#0a0a0a', ocean: '#0f3460', dracula: '#282a36', monokai: '#272822' }; const textColors = { dark: '#d4d4d4', light: '#000000', hacker: '#00ff00', ocean: '#4ec9b0', dracula: '#f8f8f2', monokai: '#f8f8f2' }; // Apply theme changes immediately document.body.style.background = bodyColors[themeName] || '#1e1e1e'; document.body.style.color = textColors[themeName] || '#d4d4d4'; // Update toolbar and sidebar colors const toolbar = document.querySelector('.toolbar'); const sidebar = document.querySelector('.sidebar'); const tabs = document.querySelectorAll('.tab'); if (themeName === 'light') { if (toolbar) { toolbar.style.background = '#f8f9fa'; toolbar.style.color = '#000000'; toolbar.style.borderBottom = '1px solid #dee2e6'; } if (sidebar) { sidebar.style.background = '#f8f9fa'; sidebar.style.color = '#000000'; sidebar.style.borderRight = '1px solid #dee2e6'; } tabs.forEach(tab => { tab.style.color = '#495057'; }); } else { if (toolbar) { toolbar.style.background = '#252526'; toolbar.style.color = '#d4d4d4'; toolbar.style.borderBottom = '1px solid #3e3e42'; } if (sidebar) { sidebar.style.background = '#252526'; sidebar.style.color = '#d4d4d4'; sidebar.style.borderRight = '1px solid #3e3e42'; } tabs.forEach(tab => { tab.style.color = '#cccccc'; }); } // Save theme preference localStorage.setItem('monaco-ide-theme', themeName); console.log('Theme applied successfully:', themeName); // Show confirmation const notification = document.createElement('div'); notification.className = 'notification success'; notification.textContent = `Theme changed to ${themeName}`; document.body.appendChild(notification); setTimeout(() => { notification.classList.add('fade-out'); setTimeout(() => notification.remove(), 300); }, 2000); } function changeTheme() { const themes = ['dark', 'light', 'hacker', 'ocean', 'dracula', 'monokai']; const currentTheme = localStorage.getItem('monaco-ide-theme') || 'dark'; const currentIndex = themes.indexOf(currentTheme); const nextTheme = themes[(currentIndex + 1) % themes.length]; setTheme(nextTheme); document.getElementById('theme-select').value = nextTheme; } // Settings management function openSettings() { document.getElementById('settings-modal').classList.add('show'); } function saveSettings() { const fontSize = document.getElementById('font-size').value; const tabSize = document.getElementById('tab-size').value; const wordWrap = document.getElementById('word-wrap').value; const minimap = document.getElementById('minimap').value === 'true'; if (editor) { editor.updateOptions({ fontSize: parseInt(fontSize), tabSize: parseInt(tabSize), insertSpaces: true, wordWrap: wordWrap, minimap: { enabled: minimap } }); } // Save settings to localStorage const settings = { fontSize, tabSize, wordWrap, minimap }; localStorage.setItem('monaco-ide-settings', JSON.stringify(settings)); closeModal(); showNotification('Settings saved successfully', 'success'); } // Modal management function closeModal() { document.querySelectorAll('.modal').forEach(modal => modal.classList.remove('show')); } // File operations function newFolder() { log('New folder functionality not yet implemented', 'warning'); } function openFileDialog() { log('Open file dialog not yet implemented', 'warning'); } // Command copy functionality async function copyCommand(command, event) { event.stopPropagation(); // Prevent executing the command try { await navigator.clipboard.writeText(command); showCommandFeedback(event.target.parentElement); showNotification(`Copied "${command}" to clipboard`, 'success'); } catch (error) { showNotification('Failed to copy to clipboard', 'error'); } } // Command execution feedback function showCommandFeedback(buttonElement) { const originalText = buttonElement.textContent; buttonElement.innerHTML = 'โœ…'; setTimeout(() => { buttonElement.innerHTML = '๐Ÿ“‹'; }, 1000); } // External command execution (from cheatsheet) function executeExternalCommand(command) { // Dispatch event as specified in documentation window.dispatchEvent(new CustomEvent('terminal:execute', { detail: { command: command } })); // Also execute directly executeCommand(command); } // Listen for external command execution window.addEventListener('terminal:execute', (event) => { const { command } = event.detail; executeCommand(command); }); // Terminal toggle functionality function toggleTerminal() { const terminal = document.querySelector('.terminal'); const editorSection = document.querySelector('.editor-section'); const toggleBtn = document.getElementById('terminal-toggle-btn'); if (terminal.style.display === 'none') { terminal.style.display = 'flex'; editorSection.style.height = 'calc(100% - 250px)'; toggleBtn.textContent = '๐Ÿ’ป Terminal'; toggleBtn.className = 'btn btn-success'; showNotification('Terminal shown - Type "help" for commands', 'success'); log('Terminal activated. Type "help" to see available commands.', 'success'); } else { terminal.style.display = 'none'; editorSection.style.height = '100%'; toggleBtn.textContent = '๐Ÿ’ป Terminal'; toggleBtn.className = 'btn btn-ghost'; showNotification('Terminal hidden', 'success'); } // Resize Monaco editor if (editor) { setTimeout(() => editor.layout(), 100); } } // Enhanced terminal theme system function applyTerminalTheme(themeName) { const terminal = document.querySelector('.terminal'); const output = document.getElementById('terminal-output'); const input = document.getElementById('terminal-input'); // Remove existing theme classes terminal.className = terminal.className.replace(/terminal-theme-\w+/g, '').trim(); if (themeName && themeName !== 'default') { terminal.classList.add(`terminal-theme-${themeName}`); const themeStyles = { hacker: { background: '#0a0a0a', color: '#00ff00', prompt: '#00ff00' }, ocean: { background: '#0f3460', color: '#4ec9b0', prompt: '#4ec9b0' }, dracula: { background: '#282a36', color: '#f8f8f2', prompt: '#50fa7b' }, monokai: { background: '#272822', color: '#f8f8f2', prompt: '#a6e22e' } }; if (themeStyles[themeName]) { const theme = themeStyles[themeName]; output.style.background = theme.background; output.style.color = theme.color; document.querySelector('.terminal-prompt').style.color = theme.prompt; input.style.color = theme.color; input.style.background = theme.background; } } else { // Default theme output.style.background = '#1e1e1e'; output.style.color = '#d4d4d4'; document.querySelector('.terminal-prompt').style.color = '#4ec9b0'; input.style.color = '#d4d4d4'; input.style.background = '#252526'; } localStorage.setItem('terminal-theme', themeName || 'default'); } // Terminal search functionality function searchTerminal(query) { const lines = document.querySelectorAll('.terminal-line'); let found = false; lines.forEach(line => { const text = line.textContent.toLowerCase(); if (text.includes(query.toLowerCase())) { line.style.background = '#4ec9b0'; line.style.color = '#1e1e1e'; found = true; setTimeout(() => { line.style.background = ''; line.style.color = ''; }, 2000); } }); if (found) { log(`Found matches for "${query}"`, 'success'); } else { log(`No matches found for "${query}"`, 'warning'); } } // Enhanced command suggestions function getCommandSuggestions() { const suggestions = [ 'help - Show all commands', 'ls - List files', 'save - Save current file', 'preview - Create live preview', 'deploy - Deploy to Cloudflare', 'clear - Clear terminal', 'history - View command history', 'achievements - View achievements', 'status - System health check', 'files - List files in VFS', 'build - Build project', 'test - Run tests', 'git status - Check git status', 'git add . - Stage all files', 'git commit -m "message" - Commit changes', 'git push - Push to remote', 'wrangler dev - Start dev server', 'wrangler deploy - Deploy worker', 'wrangler pages deploy - Deploy to Pages', 'npm install - Install dependencies', 'npm run build - Build project', 'npm test - Run tests' ]; log('Command Suggestions:', 'warning'); suggestions.forEach(suggestion => log(` ${suggestion}`, '')); log('', ''); log('Type any command or use Tab for completion', 'success'); } // Notifications function showNotification(message, type = 'info') { const notification = document.createElement('div'); notification.className = `notification ${type}`; notification.textContent = message; document.body.appendChild(notification); setTimeout(() => { notification.classList.add('fade-out'); setTimeout(() => { if (notification.parentNode) { notification.parentNode.removeChild(notification); } }, 300); }, 3000); } // Live preview functions let currentPreviewUrl = null; function refreshPreview() { if (currentPreviewUrl) { const iframe = document.querySelector('#preview-container iframe'); if (iframe) { iframe.src = iframe.src; log('Preview refreshed', 'success'); } } else { log('No active preview to refresh', 'warning'); } } function openPreviewExternal() { if (currentPreviewUrl) { window.open(currentPreviewUrl, '_blank'); } else { log('No active preview to open', 'warning'); } } // Update preview display function updatePreviewDisplay(previewUrl) { currentPreviewUrl = previewUrl; const container = document.getElementById('preview-container'); const status = document.getElementById('preview-status'); if (previewUrl) { container.innerHTML = ''; status.textContent = previewUrl; } else { container.innerHTML = '
    ๐Ÿ‘๏ธ
    Live Preview
    Click Preview to see your app in action
    Edge runtime renders without build step
    '; status.textContent = 'No preview active'; } } // Infrastructure Wizard Functions let infraStep = 1; let infraApiToken = ''; let infraAccountId = ''; let infraAnalysis = null; let infraResources = null; function openInfrastructureWizard() { infraStep = 1; infraApiToken = ''; infraAccountId = ''; infraAnalysis = null; infraResources = null; document.getElementById('infra-title').textContent = 'Setup Cloudflare Infrastructure'; document.getElementById('infra-step-1').style.display = 'block'; document.getElementById('infra-step-2').style.display = 'none'; document.getElementById('infra-step-3').style.display = 'none'; document.getElementById('infra-step-4').style.display = 'none'; document.getElementById('infra-primary-btn').textContent = 'Validate & Continue'; document.getElementById('infra-modal').classList.add('show'); } function infraNextStep() { if (infraStep === 1) { validateInfraToken(); } else if (infraStep === 2) { provisionInfraResources(); } else if (infraStep === 3) { completeInfraSetup(); } else if (infraStep === 4) { closeModal(); } } async function validateInfraToken() { infraApiToken = document.getElementById('infra-api-token').value; infraAccountId = document.getElementById('infra-account-id').value; if (!infraApiToken || !infraAccountId) { showNotification('Please fill in all fields', 'error'); return; } document.getElementById('infra-primary-btn').disabled = true; document.getElementById('infra-primary-btn').textContent = 'Validating...'; try { // Validate token with Cloudflare API const response = await fetch('https://api.cloudflare.com/client/v4/user/tokens/verify', { headers: { Authorization: 'Bearer ' + infraApiToken } }); if (!response.ok) { throw new Error('Invalid API token'); } const data = await response.json(); if (!data.success) { throw new Error('Token validation failed'); } // Analyze project infraAnalysis = analyzeProjectForInfra(); showInfraStep2(); } catch (error) { showNotification('Token validation failed: ' + error.message, 'error'); document.getElementById('infra-primary-btn').disabled = false; document.getElementById('infra-primary-btn').textContent = 'Validate & Continue'; } } function analyzeProjectForInfra() { const files = {}; fileSystem.forEach((content, filename) => { files[filename] = content; }); const fileNames = Object.keys(files); const analysis = { type: 'web-app', framework: 'unknown', needsAuth: false, needsDatabase: false, needsStorage: false, needsRealtime: false, resources: [] }; // Detect framework if (fileNames.some(f => f.includes('next'))) { analysis.framework = 'Next.js'; analysis.type = 'fullstack-app'; } else if (fileNames.some(f => f.includes('react'))) { analysis.framework = 'React'; } else if (fileNames.some(f => f.includes('vue'))) { analysis.framework = 'Vue.js'; } else if (fileNames.some(f => f.includes('angular'))) { analysis.framework = 'Angular'; } // Detect needs const content = Object.values(files).join(' ').toLowerCase(); if (content.includes('auth') || content.includes('login') || content.includes('session')) { analysis.needsAuth = true; analysis.resources.push('KV Namespace for sessions'); } if (content.includes('database') || content.includes('db') || content.includes('sql') || content.includes('d1')) { analysis.needsDatabase = true; analysis.resources.push('D1 Database'); } if (content.includes('storage') || content.includes('upload') || content.includes('file') || content.includes('r2')) { analysis.needsStorage = true; analysis.resources.push('R2 Bucket for file storage'); } if (content.includes('websocket') || content.includes('realtime') || content.includes('live') || content.includes('durable')) { analysis.needsRealtime = true; analysis.resources.push('Durable Objects for WebSockets'); } return analysis; } function showInfraStep2() { infraStep = 2; document.getElementById('infra-title').textContent = 'Infrastructure Plan'; document.getElementById('infra-step-1').style.display = 'none'; document.getElementById('infra-step-2').style.display = 'block'; const resultsDiv = document.getElementById('analysis-results'); resultsDiv.innerHTML = `
    Project Type: ${infraAnalysis.type}
    Framework: ${infraAnalysis.framework}
    Resources to Create:
      ${infraAnalysis.resources.map(r => `
    • ${r}
    • `).join('')}
    `; document.getElementById('infra-primary-btn').disabled = false; document.getElementById('infra-primary-btn').textContent = 'Create Infrastructure'; } async function provisionInfraResources() { infraStep = 3; document.getElementById('infra-title').textContent = 'Provisioning Resources'; document.getElementById('infra-step-2').style.display = 'none'; document.getElementById('infra-step-3').style.display = 'block'; document.getElementById('infra-primary-btn').disabled = true; document.getElementById('infra-primary-btn').textContent = 'Provisioning...'; try { // Simulate resource creation const resources = []; if (infraAnalysis.needsAuth) { resources.push({ type: 'kv_namespace', name: 'SESSION_STATE', id: 'generated-kv-id-' + Date.now() }); } if (infraAnalysis.needsDatabase) { resources.push({ type: 'd1_database', name: 'APP_DB', id: 'generated-d1-id-' + Date.now() }); } if (infraAnalysis.needsStorage) { resources.push({ type: 'r2_bucket', name: 'APP_STORAGE', id: 'generated-r2-id-' + Date.now() }); } if (infraAnalysis.needsRealtime) { resources.push({ type: 'durable_object', name: 'WS_HANDLER', class: 'WebSocketHandler' }); } // Add default resources resources.push( { type: 'kv_namespace', name: 'USER_DATA', id: 'generated-user-kv-' + Date.now() }, { type: 'r2_bucket', name: 'ASSETS', id: 'generated-assets-r2-' + Date.now() } ); infraResources = resources; setTimeout(() => { showInfraStep4(); }, 3000); } catch (error) { showNotification('Provisioning failed: ' + error.message, 'error'); document.getElementById('infra-primary-btn').disabled = false; document.getElementById('infra-primary-btn').textContent = 'Retry'; } } function showInfraStep4() { infraStep = 4; document.getElementById('infra-title').textContent = 'Configuration Complete'; document.getElementById('infra-step-3').style.display = 'none'; document.getElementById('infra-step-4').style.display = 'block'; const configDiv = document.getElementById('wrangler-config'); configDiv.textContent = generateWranglerConfig(); document.getElementById('infra-primary-btn').disabled = false; document.getElementById('infra-primary-btn').textContent = 'Save Configuration'; } function generateWranglerConfig() { let config = `name = "my-project" compatibility_date = "2025-01-01" main = "worker.js" `; infraResources.forEach(resource => { if (resource.type === 'd1_database') { config += `[[d1_databases]] binding = "${resource.name}" database_name = "${resource.name.toLowerCase()}" database_id = "${resource.id}" `; } else if (resource.type === 'kv_namespace') { config += `[[kv_namespaces]] binding = "${resource.name}" id = "${resource.id}" `; } else if (resource.type === 'r2_bucket') { config += `[[r2_buckets]] binding = "${resource.name}" bucket_name = "${resource.name.toLowerCase().replace('_', '-')}" preview_bucket_name = "${resource.name.toLowerCase().replace('_', '-')}-preview" `; } else if (resource.type === 'durable_object') { config += `[[durable_objects.bindings]] name = "${resource.name}" class_name = "${resource.class}" `; } }); config += `[[migrations]] tag = "v1" new_sqlite_classes = ["WebSocketHandler"] [vars] ENVIRONMENT = "production"`; return config; } function completeInfraSetup() { // Save the wrangler.toml file const config = generateWranglerConfig(); fileSystem.set('wrangler.toml', config, 'ini'); renderFileList(); // Create a worker.js template const workerTemplate = 'export default {\n async fetch(request, env, ctx) {\n const { DB, STORAGE, KV } = env;\n\n // Your Cloudflare Worker code here\n return new Response(\'Hello from Cloudflare Workers!\', {\n headers: { \'Content-Type\': \'text/plain\' }\n });\n }\n}\n\ninterface Env {\n DB: D1Database;\n STORAGE: R2Bucket;\n KV: KVNamespace;\n}'; fileSystem.set('worker.js', workerTemplate, 'javascript'); renderFileList(); showNotification('Infrastructure setup complete! wrangler.toml and worker.js created.', 'success'); closeModal(); } // Infrastructure Wizard System let infraWizard = { step: 1, apiToken: '', accountId: '', analysis: null, resources: null, init() { // Add infrastructure wizard tab if not exists const tabsContainer = document.querySelector('.sidebar-tabs'); if (!document.getElementById('infra-tab')) { const infraTab = document.createElement('div'); infraTab.className = 'tab'; infraTab.id = 'infra-tab'; infraTab.textContent = '\uD83D\uDEE0\uFE0F'; infraTab.title = 'Infrastructure Wizard'; infraTab.onclick = () => openInfrastructureWizard(); tabsContainer.appendChild(infraTab); } }, async analyzeProject(files) { const analysis = { type: 'web-app', framework: 'unknown', needsAuth: false, needsDatabase: false, needsStorage: false, needsRealtime: false, resources: [] }; // Detect framework if (files['next.config.js'] || files['next.config.mjs'] || files['next.config.ts']) { analysis.framework = 'Next.js'; analysis.type = 'fullstack-app'; } else if (files['package.json'] && files['package.json'].includes('react')) { analysis.framework = 'React'; } // Detect needs from file content const content = Object.values(files).join(' ').toLowerCase(); if (content.includes('auth') || content.includes('login') || content.includes('session')) { analysis.needsAuth = true; analysis.resources.push('KV Namespace for sessions'); } if (content.includes('database') || content.includes('db') || content.includes('sql') || content.includes('d1')) { analysis.needsDatabase = true; analysis.resources.push('D1 Database'); } if (content.includes('storage') || content.includes('upload') || content.includes('file') || content.includes('r2')) { analysis.needsStorage = true; analysis.resources.push('R2 Bucket for file storage'); } if (content.includes('websocket') || content.includes('realtime') || content.includes('live') || content.includes('durable')) { analysis.needsRealtime = true; analysis.resources.push('Durable Objects for WebSockets'); } return analysis; }, async validateToken() { if (!this.apiToken || !this.accountId) { showNotification('Please fill in all fields', 'error'); return false; } try { showNotification('Validating API token...', 'warning'); // For demo purposes, we'll simulate validation await new Promise(resolve => setTimeout(resolve, 2000)); const files = {}; fileSystem.forEach((content, filename) => { files[filename] = content; }); this.analysis = await this.analyzeProject(files); return true; } catch (error) { showNotification('Token validation failed: ' + error.message, 'error'); return false; } }, async provisionResources() { try { showNotification('Provisioning Cloudflare resources...', 'warning'); // Simulate resource creation this.resources = { kv: [{ name: 'SESSION_STATE', id: 'kv-' + Date.now() }], d1: [{ name: 'APP_DB', id: 'd1-' + Date.now() }], r2: [{ name: 'APP_STORAGE', id: 'r2-' + Date.now() }], workers: [{ name: 'main-worker', url: 'https://worker.example.com' }] }; await new Promise(resolve => setTimeout(resolve, 3000)); return true; } catch (error) { showNotification('Provisioning failed: ' + error.message, 'error'); return false; } }, generateConfig() { let config = 'name = "my-project"\ncompatibility_date = "2025-01-01"\nmain = "_worker.js"\n\n'; if (this.resources.kv && this.resources.kv.length > 0) { config += '[[kv_namespaces]]\n'; config += 'binding = "' + this.resources.kv[0].name + '"\n'; config += 'id = "' + this.resources.kv[0].id + '"\n\n'; } if (this.resources.d1 && this.resources.d1.length > 0) { config += '[[d1_databases]]\n'; config += 'binding = "' + this.resources.d1[0].name + '"\n'; config += 'database_name = "' + this.resources.d1[0].name.toLowerCase() + '"\n'; config += 'database_id = "' + this.resources.d1[0].id + '"\n\n'; } if (this.resources.r2 && this.resources.r2.length > 0) { config += '[[r2_buckets]]\n'; config += 'binding = "' + this.resources.r2[0].name + '"\n'; config += 'bucket_name = "' + this.resources.r2[0].name.toLowerCase().replace('_', '-') + '"\n\n'; } config += '[[migrations]]\n'; config += 'tag = "v1"\n'; config += 'new_sqlite_classes = ["WebSocketHandler"]\n\n'; config += '[vars]\n'; config += 'ENVIRONMENT = "production"\n'; return config; } }; // Infrastructure Wizard UI Functions function openInfrastructureWizard() { infraWizard.step = 1; infraWizard.apiToken = ''; infraWizard.accountId = ''; infraWizard.analysis = null; infraWizard.resources = null; // Switch to infrastructure tab document.querySelectorAll('.tab').forEach(tab => tab.classList.remove('active')); document.getElementById('infra-tab').classList.add('active'); // Hide other content document.querySelectorAll('.sidebar-content > div').forEach(content => { content.classList.remove('show'); }); // Show infrastructure wizard const infraModal = document.getElementById('infra-modal'); infraModal.classList.add('show'); showInfraStep(1); } function showInfraStep(step) { infraWizard.step = step; document.getElementById('infra-step-1').style.display = step === 1 ? 'block' : 'none'; document.getElementById('infra-step-2').style.display = step === 2 ? 'block' : 'none'; document.getElementById('infra-step-3').style.display = step === 3 ? 'block' : 'none'; document.getElementById('infra-step-4').style.display = step === 4 ? 'block' : 'none'; const titleElement = document.getElementById('infra-title'); const primaryBtn = document.getElementById('infra-primary-btn'); switch(step) { case 1: titleElement.textContent = 'Setup Cloudflare Infrastructure'; primaryBtn.textContent = 'Validate & Continue'; primaryBtn.onclick = () => infraWizard.validateToken().then(success => { if (success) showInfraStep(2); }); break; case 2: titleElement.textContent = 'Infrastructure Plan'; updateInfraAnalysis(); primaryBtn.textContent = 'Create Infrastructure'; primaryBtn.onclick = () => infraWizard.provisionResources().then(success => { if (success) showInfraStep(3); }); break; case 3: titleElement.textContent = 'Provisioning Resources'; setTimeout(() => showInfraStep(4), 3000); primaryBtn.style.display = 'none'; break; case 4: titleElement.textContent = 'Configuration Complete'; updateInfraConfig(); primaryBtn.style.display = 'block'; primaryBtn.textContent = 'Save Configuration'; primaryBtn.onclick = completeInfraSetup; break; } } function updateInfraAnalysis() { const resultsDiv = document.getElementById('analysis-results'); if (infraWizard.analysis) { resultsDiv.innerHTML = '
    ' + 'Project Type: ' + infraWizard.analysis.type + '
    ' + 'Framework: ' + infraWizard.analysis.framework + '
    ' + '
    ' + 'Resources to Create:' + '
      ' + infraWizard.analysis.resources.map(r => '
    • ' + r + '
    • ').join('') + '
    ' + '
    '; } } function updateInfraConfig() { const configDiv = document.getElementById('wrangler-config'); configDiv.textContent = infraWizard.generateConfig(); } function completeInfraSetup() { const config = infraWizard.generateConfig(); // Save wrangler.toml fileSystem.set('wrangler.toml', config, 'ini'); renderFileList(); // Create worker template const workerTemplate = 'export default {\n async fetch(request, env, ctx) {\n const { DB, STORAGE, KV } = env;\n\n // Your Cloudflare Worker code here\n return new Response(\'Hello from Cloudflare Workers!\', {\n headers: { \'Content-Type\': \'text/plain\' }\n });\n }\n};\n\ninterface Env {\n DB: D1Database;\n STORAGE: R2Bucket;\n KV: KVNamespace;\n}'; fileSystem.set('_worker.js', workerTemplate, 'javascript'); renderFileList(); showNotification('Infrastructure setup complete! wrangler.toml and _worker.js created.', 'success'); closeModal(); } // Update achievements display function updateAchievementsDisplay() { const achievementList = achievements.getAchievements(); achievementList.forEach(achievement => { const achievementElement = document.querySelector(`[data-achievement="${achievement.id}"]`); if (achievementElement) { achievementElement.classList.toggle('achievement-locked', !achievement.unlocked); const progressElement = achievementElement.querySelector('.achievement-progress'); if (progressElement) { const statKey = achievement.id.replace('-', ''); const currentValue = achievements.getStats()[statKey] || 0; progressElement.textContent = achievement.unlocked ? '' : `(${currentValue}/${achievement.condition})`; } } }); } // Override createPreview to update the UI const originalCreatePreview = createPreview; createPreview = async function() { await originalCreatePreview(); // After creating preview, update the live preview panel if we're on that tab const activeTab = document.querySelector('.tab.active'); if (activeTab && activeTab.textContent.trim() === '๐Ÿ‘๏ธ') { // The preview URL would need to be captured from the log or stored globally // For now, we'll just refresh the placeholder setTimeout(() => { log('Preview created! Switch to Preview tab to view it.', 'success'); }, 1000); } }; // Load saved settings on startup window.addEventListener('load', () => { // Initialize infrastructure wizard infraWizard.init(); // Load saved files const saved = localStorage.getItem('monaco-ide-fs'); if (saved) { const data = JSON.parse(saved); fileSystem.clear(); data.forEach(([k, v]) => fileSystem.set(k, v)); renderFileList(); } // Load saved theme const savedTheme = localStorage.getItem('monaco-ide-theme') || 'dark'; document.getElementById('theme-select').value = savedTheme; setTheme(savedTheme); // Load saved settings const savedSettings = localStorage.getItem('monaco-ide-settings'); if (savedSettings) { const settings = JSON.parse(savedSettings); document.getElementById('font-size').value = settings.fontSize || '14'; document.getElementById('tab-size').value = settings.tabSize || '2'; document.getElementById('word-wrap').value = settings.wordWrap || 'bounded'; document.getElementById('minimap').value = settings.minimap ? 'true' : 'false'; if (editor) { editor.updateOptions({ fontSize: parseInt(settings.fontSize || '14'), tabSize: parseInt(settings.tabSize || '2'), insertSpaces: true, wordWrap: settings.wordWrap || 'bounded', minimap: { enabled: settings.minimap || false } }); } } // Update achievements display updateAchievementsDisplay(); log('Monaco IDE initialized. Type "help" in terminal for commands.', 'success'); });