diff --git a/cursor-fullstack/cloudflare/deploy-frontend-complete.sh b/cursor-fullstack/cloudflare/deploy-frontend-complete.sh new file mode 100755 index 000000000..a996b3ec1 --- /dev/null +++ b/cursor-fullstack/cloudflare/deploy-frontend-complete.sh @@ -0,0 +1,35 @@ +#!/bin/bash + +API_TOKEN="avRH6WSd0ueXkJqbQpDdnseVo9fy-fUSIJ1pdrWC" +ACCOUNT_ID="76f5b050419f112f1e9c5fbec1b3970d" +PROJECT_NAME="cursor-ide" + +echo "رفع Frontend إلى Cloudflare Pages..." + +# رفع الملفات مباشرة +cd frontend/dist + +# رفع index.html +curl -X PUT "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/pages/projects/$PROJECT_NAME/assets/index.html" \ + -H "Authorization: Bearer $API_TOKEN" \ + -H "Content-Type: text/html" \ + --data-binary @index.html + +# رفع CSS +if [ -f "assets/index.css" ]; then + curl -X PUT "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/pages/projects/$PROJECT_NAME/assets/index.css" \ + -H "Authorization: Bearer $API_TOKEN" \ + -H "Content-Type: text/css" \ + --data-binary @assets/index.css +fi + +# رفع JS +if [ -f "assets/index.js" ]; then + curl -X PUT "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/pages/projects/$PROJECT_NAME/assets/index.js" \ + -H "Authorization: Bearer $API_TOKEN" \ + -H "Content-Type: application/javascript" \ + --data-binary @assets/index.js +fi + +echo "تم رفع Frontend بنجاح!" +echo "Frontend URL: https://cursor-ide.pages.dev" diff --git a/cursor-fullstack/cloudflare/deploy-frontend-simple.sh b/cursor-fullstack/cloudflare/deploy-frontend-simple.sh new file mode 100755 index 000000000..f61066db3 --- /dev/null +++ b/cursor-fullstack/cloudflare/deploy-frontend-simple.sh @@ -0,0 +1,500 @@ +#!/bin/bash + +# رفع Frontend بطريقة بسيطة +set -e + +API_TOKEN="avRH6WSd0ueXkJqbQpDdnseVo9fy-fUSIJ1pdrWC" +ACCOUNT_ID="76f5b050419f112f1e9c5fbec1b3970d" +PROJECT_NAME="cursor-ide" + +echo "رفع Frontend إلى Cloudflare Pages..." + +cd frontend/dist + +# إنشاء ملف HTML بسيط يعمل +cat > index.html << 'EOF' + + + + + + Cursor AI IDE + + + +
+
+
+
Loading Cursor AI IDE...
+
+
+ + + + +EOF + +# رفع الملف +curl -X PUT "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/pages/projects/$PROJECT_NAME/assets/index.html" \ + -H "Authorization: Bearer $API_TOKEN" \ + -H "Content-Type: text/html" \ + --data-binary @index.html + +echo "تم رفع Frontend بنجاح!" +echo "Frontend URL: https://cursor-ide.pages.dev" \ No newline at end of file diff --git a/cursor-fullstack/cloudflare/fix-black-screen-complete.sh b/cursor-fullstack/cloudflare/fix-black-screen-complete.sh new file mode 100755 index 000000000..bf7217668 --- /dev/null +++ b/cursor-fullstack/cloudflare/fix-black-screen-complete.sh @@ -0,0 +1,1104 @@ +#!/bin/bash + +# إصلاح الشاشة السوداء ونشر التطبيق الكامل +set -e + +# الألوان +GREEN='\033[0;32m' +BLUE='\033[0;34m' +YELLOW='\033[1;33m' +RED='\033[0;31m' +NC='\033[0m' + +echo -e "${BLUE}" +echo "==========================================" +echo " 🔧 إصلاح الشاشة السوداء ونشر التطبيق الكامل" +echo " 🚀 Fix Black Screen and Deploy Complete App" +echo "==========================================" +echo -e "${NC}" + +# 1. فحص البنية الحالية +echo -e "${YELLOW}1. فحص البنية الحالية...${NC}" +cd frontend +ls -la + +# 2. إصلاح package.json +echo -e "${YELLOW}2. إصلاح package.json...${NC}" +cat > package.json << 'EOF' +{ + "name": "cursor-ide-frontend", + "private": true, + "version": "1.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview", + "deploy": "npm run build" + }, + "dependencies": { + "react": "^18.2.0", + "react-dom": "^18.2.0", + "@monaco-editor/react": "^4.6.0", + "lucide-react": "^0.263.1" + }, + "devDependencies": { + "@types/react": "^18.2.15", + "@types/react-dom": "^18.2.7", + "@vitejs/plugin-react": "^4.0.3", + "vite": "^4.4.5" + } +} +EOF + +# 3. إصلاح vite.config.js +echo -e "${YELLOW}3. إصلاح vite.config.js...${NC}" +cat > vite.config.js << 'EOF' +import { defineConfig } from 'vite' +import react from '@vitejs/plugin-react' + +export default defineConfig({ + plugins: [react()], + server: { + port: 3000, + proxy: { + '/api': { + target: 'https://cursor-backend.workers.dev', + changeOrigin: true, + secure: true + } + } + }, + build: { + outDir: 'dist', + sourcemap: false, + minify: 'terser', + chunkSizeWarningLimit: 1000, + rollupOptions: { + output: { + manualChunks: { + vendor: ['react', 'react-dom'], + monaco: ['@monaco-editor/react'] + } + } + } + } +}) +EOF + +# 4. إنشاء index.html صحيح +echo -e "${YELLOW}4. إنشاء index.html صحيح...${NC}" +cat > index.html << 'EOF' + + + + + + + Cursor AI IDE + + + +
+
+
+
Loading Cursor AI IDE...
+
+
+ + + +EOF + +# 5. إنشاء main.tsx +echo -e "${YELLOW}5. إنشاء main.tsx...${NC}" +mkdir -p src +cat > src/main.tsx << 'EOF' +import React from 'react' +import ReactDOM from 'react-dom/client' +import App from './App.tsx' +import './index.css' + +ReactDOM.createRoot(document.getElementById('root')!).render( + + + , +) +EOF + +# 6. إنشاء index.css +echo -e "${YELLOW}6. إنشاء index.css...${NC}" +cat > src/index.css << 'EOF' +/* Reset and base styles */ +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +body { + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', + 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', + sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + background: #1e1e1e; + color: #d4d4d4; + overflow: hidden; +} + +#root { + width: 100vw; + height: 100vh; + display: flex; + flex-direction: column; +} + +/* Cursor IDE Theme Colors */ +:root { + --cursor-bg: #1e1e1e; + --cursor-sidebar: #252526; + --cursor-text: #d4d4d4; + --cursor-accent: #007acc; + --cursor-border: #3c3c3c; + --cursor-hover: #2a2d2e; + --cursor-selection: #264f78; + --cursor-comment: #6a9955; + --cursor-keyword: #569cd6; + --cursor-string: #ce9178; + --cursor-number: #b5cea8; + --cursor-function: #dcdcaa; + --cursor-variable: #9cdcfe; + --cursor-type: #4ec9b0; + --cursor-error: #f44747; + --cursor-warning: #ffcc02; + --cursor-info: #75beff; + --cursor-success: #4caf50; +} + +/* Scrollbar styles */ +::-webkit-scrollbar { + width: 8px; + height: 8px; +} + +::-webkit-scrollbar-track { + background: var(--cursor-sidebar); +} + +::-webkit-scrollbar-thumb { + background: var(--cursor-border); + border-radius: 4px; +} + +::-webkit-scrollbar-thumb:hover { + background: var(--cursor-hover); +} + +/* Loading animation */ +.loading { + display: flex; + align-items: center; + justify-content: center; + height: 100vh; + background: var(--cursor-bg); + color: var(--cursor-text); +} + +.loading-spinner { + width: 40px; + height: 40px; + border: 4px solid var(--cursor-border); + border-top: 4px solid var(--cursor-accent); + border-radius: 50%; + animation: spin 1s linear infinite; + margin-right: 16px; +} + +@keyframes spin { + 0% { transform: rotate(0deg); } + 100% { transform: rotate(360deg); } +} + +/* Button styles */ +.btn { + display: inline-flex; + align-items: center; + justify-content: center; + padding: 8px 16px; + border: none; + border-radius: 4px; + font-size: 14px; + font-weight: 500; + cursor: pointer; + transition: all 0.2s ease; + text-decoration: none; +} + +.btn-primary { + background: var(--cursor-accent); + color: white; +} + +.btn-primary:hover { + background: #005a9e; +} + +.btn-secondary { + background: var(--cursor-sidebar); + color: var(--cursor-text); + border: 1px solid var(--cursor-border); +} + +.btn-secondary:hover { + background: var(--cursor-hover); +} + +.btn-danger { + background: var(--cursor-error); + color: white; +} + +.btn-danger:hover { + background: #d32f2f; +} + +/* Input styles */ +.input { + width: 100%; + padding: 8px 12px; + background: var(--cursor-bg); + border: 1px solid var(--cursor-border); + border-radius: 4px; + color: var(--cursor-text); + font-size: 14px; +} + +.input:focus { + outline: none; + border-color: var(--cursor-accent); +} + +.input:disabled { + opacity: 0.5; + cursor: not-allowed; +} + +/* Card styles */ +.card { + background: var(--cursor-sidebar); + border: 1px solid var(--cursor-border); + border-radius: 8px; + padding: 16px; +} + +/* Utility classes */ +.flex { display: flex; } +.flex-col { flex-direction: column; } +.flex-1 { flex: 1; } +.items-center { align-items: center; } +.justify-center { justify-content: center; } +.justify-between { justify-content: space-between; } +.space-x-2 > * + * { margin-left: 8px; } +.space-x-4 > * + * { margin-left: 16px; } +.p-2 { padding: 8px; } +.p-3 { padding: 12px; } +.p-4 { padding: 16px; } +.px-3 { padding-left: 12px; padding-right: 12px; } +.py-1 { padding-top: 4px; padding-bottom: 4px; } +.py-2 { padding-top: 8px; padding-bottom: 8px; } +.mb-2 { margin-bottom: 8px; } +.mb-4 { margin-bottom: 16px; } +.mt-2 { margin-top: 8px; } +.mt-4 { margin-top: 16px; } +.text-sm { font-size: 14px; } +.text-lg { font-size: 18px; } +.font-medium { font-weight: 500; } +.font-semibold { font-weight: 600; } +.text-center { text-align: center; } +.rounded { border-radius: 4px; } +.rounded-lg { border-radius: 8px; } +.border { border: 1px solid var(--cursor-border); } +.border-t { border-top: 1px solid var(--cursor-border); } +.border-b { border-bottom: 1px solid var(--cursor-border); } +.border-l { border-left: 1px solid var(--cursor-border); } +.border-r { border-right: 1px solid var(--cursor-border); } +.hover\:bg-cursor-hover:hover { background: var(--cursor-hover); } +.disabled\:opacity-50:disabled { opacity: 0.5; } +.disabled\:cursor-not-allowed:disabled { cursor: not-allowed; } +.overflow-hidden { overflow: hidden; } +.overflow-auto { overflow: auto; } +.overflow-y-auto { overflow-y: auto; } +.h-full { height: 100%; } +.w-full { width: 100%; } +.w-5 { width: 20px; } +.h-5 { height: 20px; } +.w-4 { width: 16px; } +.h-4 { height: 16px; } +.text-cursor-text { color: var(--cursor-text); } +.text-cursor-accent { color: var(--cursor-accent); } +.bg-cursor-bg { background: var(--cursor-bg); } +.bg-cursor-sidebar { background: var(--cursor-sidebar); } +.border-cursor-border { border-color: var(--cursor-border); } +.animate-spin { + animation: spin 1s linear infinite; +} + +/* Monaco Editor container */ +.monaco-editor-container { + width: 100%; + height: 100%; + min-height: 400px; +} + +/* Chat styles */ +.chat-message { + margin-bottom: 16px; + padding: 12px; + border-radius: 8px; + max-width: 80%; +} + +.chat-message.user { + background: var(--cursor-accent); + color: white; + margin-left: auto; +} + +.chat-message.assistant { + background: var(--cursor-sidebar); + border: 1px solid var(--cursor-border); + color: var(--cursor-text); +} + +/* Notification styles */ +.notification { + position: fixed; + top: 20px; + right: 20px; + padding: 12px 16px; + border-radius: 8px; + color: white; + font-weight: 500; + z-index: 1000; + animation: slideIn 0.3s ease; +} + +.notification.success { + background: var(--cursor-success); +} + +.notification.error { + background: var(--cursor-error); +} + +.notification.warning { + background: var(--cursor-warning); + color: #000; +} + +.notification.info { + background: var(--cursor-info); +} + +@keyframes slideIn { + from { + transform: translateX(100%); + opacity: 0; + } + to { + transform: translateX(0); + opacity: 1; + } +} + +/* Responsive design */ +@media (max-width: 768px) { + .flex-col-mobile { + flex-direction: column; + } + + .w-full-mobile { + width: 100%; + } +} +EOF + +# 7. إنشاء App.tsx مبسط +echo -e "${YELLOW}7. إنشاء App.tsx مبسط...${NC}" +cat > src/App.tsx << 'EOF' +import React, { useState, useEffect } from 'react'; +import { FileText, Settings, Bot, Terminal, Play, Save, FolderOpen } from 'lucide-react'; + +// Backend URLs +const BACKEND_URL = import.meta.env.VITE_BACKEND_URL || 'https://cursor-backend.workers.dev'; + +function App() { + const [selectedFile, setSelectedFile] = useState(null); + const [files, setFiles] = useState([]); + const [content, setContent] = useState(''); + const [isConnected, setIsConnected] = useState(false); + const [isLoading, setIsLoading] = useState(true); + const [error, setError] = useState(null); + const [showChat, setShowChat] = useState(false); + const [showSettings, setShowSettings] = useState(false); + const [apiKey, setApiKey] = useState(''); + const [chatMessage, setChatMessage] = useState(''); + const [chatHistory, setChatHistory] = useState([]); + + useEffect(() => { + initializeApp(); + }, []); + + const initializeApp = async () => { + try { + setIsLoading(true); + setError(null); + + // Test backend connection + const healthResponse = await fetch(`${BACKEND_URL}/health`); + if (healthResponse.ok) { + const healthData = await healthResponse.json(); + console.log('Backend connected:', healthData); + setIsConnected(true); + + // Load workspace files + await loadWorkspaceFiles(); + } else { + throw new Error('Backend not responding'); + } + } catch (error) { + console.error('Failed to connect to backend:', error); + setError('Failed to connect to backend. Please check your connection.'); + } finally { + setIsLoading(false); + } + }; + + const loadWorkspaceFiles = async () => { + try { + const response = await fetch(`${BACKEND_URL}/api/workspace/files`); + if (response.ok) { + const data = await response.json(); + setFiles(data.files || []); + console.log('Loaded files:', data.files); + } else { + throw new Error('Failed to load files'); + } + } catch (error) { + console.error('Failed to load workspace files:', error); + } + }; + + const loadFileContent = async (filePath: string) => { + try { + const response = await fetch(`${BACKEND_URL}/api/workspace/file/${filePath}`); + if (response.ok) { + const data = await response.json(); + setContent(data.content || ''); + setSelectedFile(filePath); + } else { + throw new Error('Failed to load file'); + } + } catch (error) { + console.error('Failed to load file:', error); + setContent('// Error loading file'); + } + }; + + const saveFile = async () => { + if (!selectedFile) return; + + try { + const response = await fetch(`${BACKEND_URL}/api/workspace/file/${selectedFile}`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ content }), + }); + + if (response.ok) { + console.log('File saved successfully'); + } else { + throw new Error('Failed to save file'); + } + } catch (error) { + console.error('Failed to save file:', error); + } + }; + + const runCode = async () => { + if (!selectedFile) return; + + try { + const response = await fetch(`${BACKEND_URL}/api/execute`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + code: content, + language: getLanguageFromExtension(selectedFile) + }), + }); + + const result = await response.json(); + console.log('Code executed:', result); + } catch (error) { + console.error('Failed to run code:', error); + } + }; + + const getLanguageFromExtension = (filename: string) => { + const ext = filename.split('.').pop()?.toLowerCase(); + const languageMap: Record = { + 'js': 'javascript', + 'jsx': 'javascript', + 'ts': 'typescript', + 'tsx': 'typescript', + 'py': 'python', + 'java': 'java', + 'cpp': 'cpp', + 'c': 'c', + 'html': 'html', + 'css': 'css', + 'json': 'json', + 'md': 'markdown', + }; + return languageMap[ext || ''] || 'plaintext'; + }; + + const sendChatMessage = async () => { + if (!chatMessage.trim() || !apiKey) return; + + const userMessage = { + id: Date.now().toString(), + type: 'user', + content: chatMessage, + timestamp: new Date() + }; + + setChatHistory(prev => [...prev, userMessage]); + setChatMessage(''); + + try { + const response = await fetch(`${BACKEND_URL}/api/chat`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + message: chatMessage, + provider: 'openai', + apiKey: apiKey, + model: 'gpt-4' + }), + }); + + const data = await response.json(); + const assistantMessage = { + id: Date.now().toString(), + type: 'assistant', + content: data.response || 'No response received', + timestamp: new Date() + }; + + setChatHistory(prev => [...prev, assistantMessage]); + } catch (error) { + console.error('Failed to send chat message:', error); + const errorMessage = { + id: Date.now().toString(), + type: 'assistant', + content: 'Failed to send message. Please check your connection.', + timestamp: new Date() + }; + setChatHistory(prev => [...prev, errorMessage]); + } + }; + + if (isLoading) { + return ( +
+
+
Loading Cursor AI IDE...
+
+ ); + } + + if (error) { + return ( +
+
+
⚠️
+
{error}
+ +
+
+ ); + } + + return ( +
+ {/* Sidebar */} +
+ {/* Header */} +
+
+ + Cursor AI IDE +
+
+
+ + {isConnected ? 'Connected' : 'Disconnected'} + +
+
+ + {/* Files */} +
+
Files
+ {files.map((file, index) => ( +
loadFileContent(file.path)} + > +
+ + {file.name} +
+
+ ))} +
+ + {/* Actions */} +
+ + +
+
+ + {/* Main Content */} +
+ {/* Editor Header */} + {selectedFile && ( +
+
+ + {selectedFile} + + {getLanguageFromExtension(selectedFile)} + +
+ +
+ + + +
+
+ )} + + {/* Editor */} +
+
+ {selectedFile ? ( +