code-server/cursor-fullstack/cloudflare/deploy-with-new-token.sh
Cursor Agent eaeab01fc8 Fix: Update frontend with new version and deploy scripts
Co-authored-by: fekofal332 <fekofal332@reaxu.com>
2025-10-13 13:47:05 +00:00

692 lines
No EOL
23 KiB
Bash
Executable file
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/bin/bash
# نشر باستخدام التوكن الجديد
set -e
API_TOKEN="avRH6WSd0ueXkJqbQpDdnseVo9fy-fUSIJ1pdrWC"
ACCOUNT_ID="76f5b050419f112f1e9c5fbec1b3970d"
PROJECT_NAME="cursor-ide"
echo "🚀 نشر باستخدام التوكن الجديد..."
# 1. اختبار التوكن
echo "1. اختبار التوكن..."
TOKEN_TEST=$(curl -s -X GET "https://api.cloudflare.com/client/v4/user/tokens/verify" \
-H "Authorization: Bearer $API_TOKEN" \
-H "Content-Type: application/json")
echo "Token Test: $TOKEN_TEST"
if echo "$TOKEN_TEST" | grep -q '"success":true'; then
echo "✅ التوكن صحيح"
else
echo "❌ التوكن غير صحيح"
exit 1
fi
# 2. إنشاء مجلد جديد
echo "2. إنشاء مجلد جديد..."
rm -rf deploy
mkdir -p deploy
cd deploy
# 3. إنشاء ملف HTML جديد
echo "3. إنشاء ملف HTML جديد..."
cat > index.html << 'EOF'
<!DOCTYPE html>
<html lang="ar" dir="rtl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Cursor AI IDE - بيئة التطوير الذكية</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Tajawal', sans-serif;
background: #1e1e1e;
color: #d4d4d4;
height: 100vh;
overflow: hidden;
direction: rtl;
}
.container {
display: flex;
height: 100vh;
}
.sidebar {
width: 280px;
background: #252526;
border-left: 1px solid #3c3c3c;
padding: 20px;
overflow-y: auto;
}
.main {
flex: 1;
display: flex;
flex-direction: column;
}
.header {
background: #252526;
border-bottom: 1px solid #3c3c3c;
padding: 15px 20px;
display: flex;
align-items: center;
justify-content: space-between;
}
.editor {
flex: 1;
background: #1e1e1e;
padding: 20px;
}
.status-bar {
background: #007acc;
color: white;
padding: 8px 20px;
font-size: 12px;
display: flex;
justify-content: space-between;
}
.file-list {
margin-top: 20px;
}
.file-item {
padding: 10px 12px;
cursor: pointer;
border-radius: 6px;
margin-bottom: 4px;
transition: all 0.2s;
display: flex;
align-items: center;
gap: 8px;
}
.file-item:hover {
background: #2a2d2e;
transform: translateX(-2px);
}
.file-item.active {
background: #264f78;
border-right: 3px solid #007acc;
}
.editor-textarea {
width: 100%;
height: 100%;
background: #1e1e1e;
color: #d4d4d4;
border: none;
outline: none;
font-family: 'Fira Code', 'Consolas', 'Monaco', 'Cascadia Code', monospace;
font-size: 14px;
line-height: 1.6;
resize: none;
direction: ltr;
}
.btn {
background: #007acc;
color: white;
border: none;
padding: 10px 16px;
border-radius: 6px;
cursor: pointer;
margin-left: 8px;
font-weight: 500;
transition: all 0.2s;
display: flex;
align-items: center;
gap: 6px;
}
.btn:hover {
background: #005a9e;
transform: translateY(-1px);
}
.btn-secondary {
background: #2a2d2e;
color: #d4d4d4;
border: 1px solid #3c3c3c;
}
.btn-secondary:hover {
background: #3c3c3c;
}
.connection-status {
display: flex;
align-items: center;
gap: 8px;
font-size: 12px;
}
.status-dot {
width: 8px;
height: 8px;
border-radius: 50%;
background: #4caf50;
animation: pulse 2s infinite;
}
@keyframes pulse {
0%, 100% { opacity: 1; }
50% { opacity: 0.5; }
}
.chat-panel {
width: 350px;
background: #252526;
border-right: 1px solid #3c3c3c;
display: flex;
flex-direction: column;
}
.chat-header {
padding: 15px;
border-bottom: 1px solid #3c3c3c;
font-weight: 600;
display: flex;
align-items: center;
gap: 8px;
}
.chat-messages {
flex: 1;
padding: 15px;
overflow-y: auto;
direction: ltr;
}
.chat-input {
padding: 15px;
border-top: 1px solid #3c3c3c;
}
.chat-input input {
width: 100%;
background: #1e1e1e;
border: 1px solid #3c3c3c;
color: #d4d4d4;
padding: 10px 12px;
border-radius: 6px;
outline: none;
font-size: 14px;
}
.chat-input input:focus {
border-color: #007acc;
}
.message {
margin-bottom: 15px;
padding: 12px;
border-radius: 8px;
animation: slideIn 0.3s ease;
}
.message.user {
background: #007acc;
color: white;
margin-left: 20px;
border-bottom-right-radius: 4px;
}
.message.assistant {
background: #2a2d2e;
color: #d4d4d4;
margin-right: 20px;
border-bottom-left-radius: 4px;
border: 1px solid #3c3c3c;
}
@keyframes slideIn {
from {
opacity: 0;
transform: translateY(10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.loading {
display: flex;
align-items: center;
justify-content: center;
height: 100vh;
background: #1e1e1e;
color: #d4d4d4;
flex-direction: column;
gap: 20px;
}
.loading-spinner {
width: 50px;
height: 50px;
border: 4px solid #333;
border-top: 4px solid #007acc;
border-radius: 50%;
animation: spin 1s linear infinite;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
.hidden {
display: none;
}
.logo {
font-size: 18px;
font-weight: 700;
color: #007acc;
display: flex;
align-items: center;
gap: 8px;
}
.section-title {
font-size: 14px;
font-weight: 600;
color: #d4d4d4;
margin-bottom: 10px;
padding: 8px 0;
border-bottom: 1px solid #3c3c3c;
}
.file-icon {
font-size: 16px;
}
.welcome-message {
text-align: center;
padding: 40px 20px;
color: #888;
}
.welcome-message h3 {
color: #d4d4d4;
margin-bottom: 10px;
}
.feature-list {
list-style: none;
padding: 0;
margin-top: 20px;
}
.feature-list li {
padding: 5px 0;
color: #888;
font-size: 12px;
}
.feature-list li:before {
content: "✓ ";
color: #4caf50;
font-weight: bold;
}
</style>
</head>
<body>
<div id="app">
<div class="loading">
<div class="loading-spinner"></div>
<div>جاري تحميل Cursor AI IDE...</div>
<div style="font-size: 12px; color: #888;">Loading Cursor AI IDE...</div>
</div>
</div>
<script>
const BACKEND_URL = 'https://cursor-backend.workers.dev';
let isConnected = false;
let selectedFile = null;
let files = [];
let chatHistory = [];
let apiKey = '';
async function initApp() {
try {
// Test backend connection
const response = await fetch(`${BACKEND_URL}/health`);
if (response.ok) {
const data = await response.json();
console.log('Backend connected:', data);
isConnected = true;
await loadFiles();
renderApp();
} else {
throw new Error('Backend not responding');
}
} catch (error) {
console.error('Failed to connect:', error);
renderError('فشل في الاتصال بالخادم. يرجى التحقق من الاتصال.');
}
}
async function loadFiles() {
try {
const response = await fetch(`${BACKEND_URL}/api/workspace/files`);
if (response.ok) {
const data = await response.json();
files = data.files || [];
}
} catch (error) {
console.error('Failed to load files:', error);
}
}
function renderError(message) {
document.getElementById('app').innerHTML = `
<div class="loading">
<div style="text-align: center;">
<div style="color: #f44747; margin-bottom: 16px; font-size: 48px;">⚠️</div>
<div style="margin-bottom: 16px;">${message}</div>
<button class="btn" onclick="initApp()">إعادة المحاولة</button>
</div>
</div>
`;
}
function renderApp() {
document.getElementById('app').innerHTML = `
<div class="container">
<div class="sidebar">
<div class="logo">
<span>🚀</span>
<span>Cursor AI IDE</span>
</div>
<div class="connection-status">
<div class="status-dot" style="background: ${isConnected ? '#4caf50' : '#f44747'}"></div>
<span>${isConnected ? 'متصل' : 'غير متصل'}</span>
</div>
<div class="file-list">
<div class="section-title">📁 الملفات</div>
${files.map(file => `
<div class="file-item ${selectedFile === file.path ? 'active' : ''}"
onclick="selectFile('${file.path}')">
<span class="file-icon">📄</span>
<span>${file.name}</span>
</div>
`).join('')}
</div>
<div style="margin-top: 20px;">
<div class="section-title">🛠️ الأدوات</div>
<button class="btn btn-secondary" onclick="toggleChat()" style="width: 100%; margin: 4px 0;">
🤖 دردشة AI
</button>
<button class="btn btn-secondary" onclick="toggleSettings()" style="width: 100%; margin: 4px 0;">
⚙️ الإعدادات
</button>
</div>
</div>
<div class="main">
<div class="header">
<div>
<span>📄 ${selectedFile || 'لم يتم اختيار ملف'}</span>
</div>
<div>
<button class="btn" onclick="saveFile()">
💾 حفظ
</button>
<button class="btn" onclick="runCode()">
▶️ تشغيل
</button>
</div>
</div>
<div class="editor">
${selectedFile ? `
<textarea class="editor-textarea" id="editor" placeholder="ابدأ البرمجة...">${getFileContent()}</textarea>
` : `
<div class="welcome-message">
<div style="font-size: 48px; margin-bottom: 16px;">📁</div>
<h3>مرحباً بك في Cursor AI IDE</h3>
<p>اختر ملفاً من الشريط الجانبي لبدء البرمجة</p>
<ul class="feature-list">
<li>محرر كود متقدم</li>
<li>دردشة مع الذكاء الاصطناعي</li>
<li>إدارة الملفات</li>
<li>تنفيذ الكود</li>
<li>أدوات متكاملة</li>
</ul>
</div>
`}
</div>
<div class="status-bar">
<div>جاهز</div>
<div>Cursor AI IDE v1.0.0</div>
</div>
</div>
<div class="chat-panel hidden" id="chatPanel">
<div class="chat-header">
<span>🤖</span>
<span>دردشة AI</span>
<button onclick="toggleChat()" style="margin-right: auto; background: none; border: none; color: #888; cursor: pointer;">×</button>
</div>
<div class="chat-messages" id="chatMessages">
${chatHistory.length === 0 ? `
<div style="text-align: center; color: #666; padding: 20px;">
<div style="font-size: 48px; margin-bottom: 16px;">🤖</div>
<p>ابدأ محادثة مع الذكاء الاصطناعي</p>
<p style="font-size: 12px;">أضف مفتاح API من الإعدادات</p>
</div>
` : chatHistory.map(msg => `
<div class="message ${msg.type}">
<div>${msg.content}</div>
<div style="font-size: 11px; opacity: 0.7; margin-top: 4px;">
${new Date(msg.timestamp).toLocaleTimeString()}
</div>
</div>
`).join('')}
</div>
<div class="chat-input">
<input type="text" id="chatInput" placeholder="${apiKey ? 'اسألني أي شيء...' : 'أضف مفتاح API أولاً'}"
onkeypress="handleChatKeyPress(event)" ${!apiKey ? 'disabled' : ''}>
</div>
</div>
</div>
<div class="hidden" id="settingsModal" style="position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.7); display: flex; align-items: center; justify-content: center; z-index: 1000;">
<div style="background: #252526; border: 1px solid #3c3c3c; border-radius: 8px; padding: 20px; width: 400px;">
<h3 style="margin-bottom: 20px; color: #d4d4d4;">⚙️ الإعدادات</h3>
<div style="margin-bottom: 15px;">
<label style="display: block; margin-bottom: 5px; color: #d4d4d4;">مفتاح OpenAI API</label>
<input type="password" id="apiKeyInput" value="${apiKey}"
style="width: 100%; background: #1e1e1e; border: 1px solid #3c3c3c; color: #d4d4d4; padding: 10px; border-radius: 6px;">
</div>
<div style="text-align: left;">
<button class="btn btn-secondary" onclick="closeSettings()">إلغاء</button>
<button class="btn" onclick="saveSettings()">حفظ</button>
</div>
</div>
</div>
`;
}
function selectFile(filePath) {
selectedFile = filePath;
renderApp();
}
function getFileContent() {
return `// ${selectedFile}
console.log('مرحباً من ${selectedFile}');
function example() {
return 'هذا ملف تجريبي';
}
export default example;`;
}
function saveFile() {
if (!selectedFile) return;
console.log('Saving file:', selectedFile);
// In a real app, this would save to backend
}
function runCode() {
if (!selectedFile) return;
console.log('Running code for:', selectedFile);
// In a real app, this would execute code
}
function toggleChat() {
const chatPanel = document.getElementById('chatPanel');
chatPanel.classList.toggle('hidden');
}
function toggleSettings() {
const settingsModal = document.getElementById('settingsModal');
settingsModal.classList.toggle('hidden');
}
function closeSettings() {
const settingsModal = document.getElementById('settingsModal');
settingsModal.classList.add('hidden');
}
function saveSettings() {
apiKey = document.getElementById('apiKeyInput').value;
closeSettings();
renderApp();
}
function handleChatKeyPress(event) {
if (event.key === 'Enter') {
sendChatMessage();
}
}
async function sendChatMessage() {
const input = document.getElementById('chatInput');
const message = input.value.trim();
if (!message || !apiKey) return;
const userMessage = {
type: 'user',
content: message,
timestamp: Date.now()
};
chatHistory.push(userMessage);
input.value = '';
renderApp();
try {
const response = await fetch(`${BACKEND_URL}/api/chat`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
message: message,
provider: 'openai',
apiKey: apiKey,
model: 'gpt-4'
}),
});
const data = await response.json();
const assistantMessage = {
type: 'assistant',
content: data.response || 'لم يتم استلام رد',
timestamp: Date.now()
};
chatHistory.push(assistantMessage);
renderApp();
} catch (error) {
console.error('Failed to send chat message:', error);
const errorMessage = {
type: 'assistant',
content: 'فشل في إرسال الرسالة. يرجى التحقق من الاتصال.',
timestamp: Date.now()
};
chatHistory.push(errorMessage);
renderApp();
}
}
// Initialize app
initApp();
</script>
</body>
</html>
EOF
# 4. إنشاء manifest.json
echo "4. إنشاء manifest.json..."
cat > manifest.json << 'EOF'
{
"index.html": "index.html"
}
EOF
# 5. ضغط الملفات
echo "5. ضغط الملفات..."
zip -r app.zip index.html manifest.json
# 6. محاولة النشر بطريقة مختلفة
echo "6. محاولة النشر..."
# محاولة 1: رفع مباشر للملف
echo "محاولة 1: رفع مباشر للملف..."
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 ""
# محاولة 2: رفع مع manifest
echo "محاولة 2: رفع مع manifest..."
curl -X POST "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/pages/projects/$PROJECT_NAME/deployments" \
-H "Authorization: Bearer $API_TOKEN" \
-F "files=@app.zip" \
-F "manifest=@manifest.json"
echo ""
# 7. اختبار الموقع
echo "7. اختبار الموقع..."
sleep 5
STATUS=$(curl -s -w "%{http_code}" https://cursor-ide.pages.dev -o /dev/null)
echo "Frontend Status: $STATUS"
if [ "$STATUS" = "200" ]; then
echo "✅ الموقع يعمل!"
else
echo "❌ الموقع لا يعمل"
fi
echo ""
echo "🌐 الرابط: https://cursor-ide.pages.dev"
echo "🎉 تم الانتهاء من النشر!"
cd ..