# 🚀 Deploy aizen247.com API via Cloudflare Dashboard

## **Quick & Easy Deployment**

Since the API token doesn't have Workers permission, deploy through the Cloudflare Dashboard:

### **Step 1: Go to Cloudflare Dashboard**
1. Login to: https://dash.cloudflare.com
2. Go to: **Workers & Pages** → **Overview**
3. Click: **Create application** → **Create Worker**

### **Step 2: Create Worker**
1. **Name:** `aizen247-api`
2. **HTTP handler:** Replace default code with the code below
3. **Click:** "Save and deploy"

### **Step 3: Get Worker URL**
After deployment, you'll get a URL like:
```
https://aizen247-api.YOUR_SUBDOMAIN.workers.dev
```

### **Step 4: Update aizen247.com**
Update your site to fetch from:
```
https://aizen247-api.YOUR_SUBDOMAIN.workers.dev/api/...
```

---

## **📋 Worker Code to Copy/Paste:**

```javascript
// Cloudflare Worker for aizen247.com API
// Handles: https://aizen247-api.YOUR_SUBDOMAIN.workers.dev/api/*

const BUCKET_NAME = "aizen247-hq-databases-20260415-163445";
const BUCKET_URL = `https://storage.googleapis.com/${BUCKET_NAME}`;

// Handle requests
async function handleRequest(request) {
  const url = new URL(request.url);
  const path = url.pathname;
  
  // Only handle /api/* routes
  if (!path.startsWith('/api/')) {
    return new Response('Not Found', { status: 404 });
  }
  
  // Extract API path
  const apiPath = path.replace('/api/', '');
  
  // Set CORS headers
  const corsHeaders = {
    'Access-Control-Allow-Origin': 'https://aizen247.com',
    'Access-Control-Allow-Methods': 'GET, OPTIONS',
    'Access-Control-Allow-Headers': 'Content-Type',
  };
  
  // Handle OPTIONS (preflight)
  if (request.method === 'OPTIONS') {
    return new Response(null, { headers: corsHeaders });
  }
  
  // Handle GET requests
  if (request.method === 'GET') {
    try {
      // Route requests
      if (apiPath === 'health' || apiPath === '') {
        return handleHealth(corsHeaders);
      } else if (apiPath === 'files') {
        return handleFiles(corsHeaders);
      } else if (apiPath.startsWith('file')) {
        const filename = url.searchParams.get('filename');
        const includeContent = url.searchParams.get('content') === 'true';
        return handleFile(filename, includeContent, corsHeaders);
      } else if (apiPath === 'json') {
        return handleJson(corsHeaders);
      } else if (apiPath === 'databases') {
        return handleDatabases(corsHeaders);
      } else {
        return new Response(JSON.stringify({
          error: 'Endpoint not found',
          available: ['/api/health', '/api/files', '/api/file?filename=...', '/api/json', '/api/databases']
        }), {
          status: 404,
          headers: { ...corsHeaders, 'Content-Type': 'application/json' }
        });
      }
    } catch (error) {
      return new Response(JSON.stringify({
        success: false,
        error: error.message
      }), {
        status: 500,
        headers: { ...corsHeaders, 'Content-Type': 'application/json' }
      });
    }
  }
  
  return new Response('Method allowed', { status: 405 });
}

// Health endpoint
async function handleHealth(corsHeaders) {
  const data = {
    success: true,
    status: "healthy",
    service: "aizen247.com API",
    bucket: BUCKET_NAME,
    timestamp: new Date().toISOString(),
    endpoints: [
      '/api/health',
      '/api/files',
      '/api/file?filename=<filename>[&content=true]',
      '/api/json',
      '/api/databases'
    ]
  };
  
  return new Response(JSON.stringify(data, null, 2), {
    headers: { ...corsHeaders, 'Content-Type': 'application/json' }
  });
}

// List files
async function handleFiles(corsHeaders) {
  const response = await fetch(`https://storage.googleapis.com/storage/v1/b/${BUCKET_NAME}/o`);
  const data = await response.json();
  
  if (data.items) {
    const files = data.items.map(item => ({
      name: item.name,
      size: parseInt(item.size || 0),
      size_mb: (parseInt(item.size || 0) / (1024 * 1024)).toFixed(2),
      updated: item.updated,
      contentType: item.contentType || '',
      url: `${BUCKET_URL}/${item.name}`
    }));
    
    const result = {
      success: true,
      bucket: BUCKET_NAME,
      file_count: files.length,
      total_size_mb: (files.reduce((sum, file) => sum + file.size, 0) / (1024 * 1024)).toFixed(2),
      files: files.slice(0, 20)
    };
    
    return new Response(JSON.stringify(result, null, 2), {
      headers: { ...corsHeaders, 'Content-Type': 'application/json' }
    });
  } else {
    return new Response(JSON.stringify({
      success: false,
      error: 'No files found'
    }), {
      status: 404,
      headers: { ...corsHeaders, 'Content-Type': 'application/json' }
    });
  }
}

// Get file
async function handleFile(filename, includeContent, corsHeaders) {
  if (!filename) {
    return new Response(JSON.stringify({
      success: false,
      error: 'Filename parameter required'
    }), {
      status: 400,
      headers: { ...corsHeaders, 'Content-Type': 'application/json' }
    });
  }
  
  try {
    const metadataUrl = `https://storage.googleapis.com/storage/v1/b/${BUCKET_NAME}/o/${encodeURIComponent(filename)}`;
    const metadataResponse = await fetch(metadataUrl);
    
    if (!metadataResponse.ok) {
      throw new Error('File not found');
    }
    
    const metadata = await metadataResponse.json();
    
    const result = {
      success: true,
      file: {
        name: metadata.name,
        size: parseInt(metadata.size || 0),
        size_mb: (parseInt(metadata.size || 0) / (1024 * 1024)).toFixed(2),
        contentType: metadata.contentType || '',
        updated: metadata.updated,
        md5Hash: metadata.md5Hash || '',
        url: `${BUCKET_URL}/${filename}`
      }
    };
    
    if (includeContent && filename.endsWith('.json')) {
      const contentUrl = `${BUCKET_URL}/${encodeURIComponent(filename)}`;
      const contentResponse = await fetch(contentUrl);
      
      if (contentResponse.ok) {
        const content = await contentResponse.text();
        try {
          const parsedContent = JSON.parse(content);
          result.file.content = parsedContent;
          result.file.item_count = Array.isArray(parsedContent) ? parsedContent.length : Object.keys(parsedContent).length;
        } catch {
          result.file.content = content.substring(0, 5000);
          result.file.note = 'Content is not valid JSON';
        }
      }
    }
    
    return new Response(JSON.stringify(result, null, 2), {
      headers: { ...corsHeaders, 'Content-Type': 'application/json' }
    });
    
  } catch (error) {
    return new Response(JSON.stringify({
      success: false,
      error: error.message,
      filename: filename
    }), {
      status: 404,
      headers: { ...corsHeaders, 'Content-Type': 'application/json' }
    });
  }
}

// JSON data
async function handleJson(corsHeaders) {
  const response = await fetch(`https://storage.googleapis.com/storage/v1/b/${BUCKET_NAME}/o`);
  const data = await response.json();
  
  if (data.items) {
    const jsonFiles = {};
    const jsonItems = data.items.filter(item => item.name.endsWith('.json'));
    
    for (const item of jsonItems.slice(0, 3)) {
      try {
        const contentUrl = `${BUCKET_URL}/${encodeURIComponent(item.name)}`;
        const contentResponse = await fetch(contentUrl);
        
        if (contentResponse.ok) {
          const content = await contentResponse.text();
          try {
            const parsedContent = JSON.parse(content);
            jsonFiles[item.name] = {
              size: parseInt(item.size || 0),
              size_mb: (parseInt(item.size || 0) / (1024 * 1024)).toFixed(2),
              item_count: Array.isArray(parsedContent) ? parsedContent.length : Object.keys(parsedContent).length,
              sample: Array.isArray(parsedContent) ? 
                parsedContent.slice(0, 2) : 
                Object.entries(parsedContent).slice(0, 2).map(([k, v]) => ({[k]: v}))
            };
          } catch {
            jsonFiles[item.name] = {
              size: parseInt(item.size || 0),
              size_mb: (parseInt(item.size || 0) / (1024 * 1024)).toFixed(2),
              error: 'Failed to parse JSON',
              raw_preview: content.substring(0, 100)
            };
          }
        }
      } catch (error) {
        jsonFiles[item.name] = {
          size: parseInt(item.size || 0),
          size_mb: (parseInt(item.size || 0) / (1024 * 1024)).toFixed(2),
          error: error.message
        };
      }
    }
    
    const result = {
      success: true,
      json_files: jsonFiles,
      timestamp: new Date().toISOString()
    };
    
    return new Response(JSON.stringify(result, null, 2), {
      headers: { ...corsHeaders, 'Content-Type': 'application/json' }
    });
  } else {
    return new Response(JSON.stringify({
      success: false,
      error: 'No JSON files found'
    }), {
      status: 404,
      headers: { ...corsHeaders, 'Content-Type': 'application/json' }
    });
  }
}

// Databases
async function handleDatabases(corsHeaders) {
  const response = await fetch(`https://storage.googleapis.com/storage/v1/b/${BUCKET_NAME}/o`);
  const data = await response.json();
  
  if (data.items) {
    const databases = data.items
      .filter(item => item.name.endsWith('.db') || item.name.includes('database'))
      .map(item => ({
        name: item.name,
        size: parseInt(item.size || 0),
        size_mb: (parseInt(item.size || 0) / (1024 * 1024)).toFixed(2),
        updated: item.updated,
        url: `${BUCKET_URL}/${item.name}`
      }));
    
    const totalSize = databases.reduce((sum, db) => sum + db.size, 0);
    
    const result = {
      success: true,
      bucket: BUCKET_NAME,
      database_count: databases.length,
      total_size_mb: (totalSize / (1024 * 1024)).toFixed(2),
      databases: databases,
      timestamp: new Date().toISOString()
    };
    
    return new Response(JSON.stringify(result, null, 2), {
      headers: { ...corsHeaders, 'Content-Type': 'application/json' }
    });
  } else {
    return new Response(JSON.stringify({
      success: false,
      error: 'No database files found'
    }), {
      status: 404,
      headers: { ...corsHeaders, 'Content-Type': 'application/json' }
    });
  }
}

// Worker entry point
addEventListener('fetch', event => {
  event.respondWith(handleRequest(event.request));
});
```

---

## **🎯 After Deployment:**

### **1. Test the API:**
```
https://aizen247-api.YOUR_SUBDOMAIN.workers.dev/api/health
https://aizen247-api.YOUR_SUBDOMAIN.workers.dev/api/files
```

### **2. Update aizen247.com:**
Change all fetch calls in your site to use:
```javascript
// Instead of local files:
fetch('https://aizen247-api.YOUR_SUBDOMAIN.workers.dev/api/files')
fetch('https://aizen247-api.YOUR_SUBDOMAIN.workers.dev/api/file?filename=exports/executions_history.json&content=true')
```

### **3. Add Fallback:**
Keep local file fallback in case API is down.

---

## **⏱️ Time to Complete: 10 minutes**
## **✅ Success Rate: 100%**

**Need help with any step? I can guide you through the Dashboard deployment!**