From 02d32536a0ada6310dcdad2a8428ce450470c516 Mon Sep 17 00:00:00 2001 From: christiankrag Date: Mon, 15 Dec 2025 05:56:18 +0100 Subject: [PATCH] Fix wws runtime compatibility - use module.exports pattern MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Update api/index.js to use handler export format - Update chat/index.js to use handler export format - Update webhook/index.js to use handler export format - Remove addEventListener('fetch') pattern incompatible with wws - Remove URL API usage (not available in wws JS runtime) - Remove spread operator for better compatibility 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- api/index.js | 19 ++++------ chat/index.js | 28 +++++++-------- webhook/index.js | 93 ++++++++++++++++++++++++++---------------------- 3 files changed, 72 insertions(+), 68 deletions(-) diff --git a/api/index.js b/api/index.js index 037a314..a63a7b2 100644 --- a/api/index.js +++ b/api/index.js @@ -1,22 +1,17 @@ // Health check and API info endpoint // Path: /api -addEventListener('fetch', event => { - event.respondWith(handleRequest(event.request)) -}) - -async function handleRequest(request) { - const url = new URL(request.url) - +async function handler(request) { // CORS headers for browser requests const corsHeaders = { 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Methods': 'GET, POST, OPTIONS', 'Access-Control-Allow-Headers': 'Content-Type, Authorization', + 'Content-Type': 'application/json' } if (request.method === 'OPTIONS') { - return new Response(null, { headers: corsHeaders }) + return new Response('', { headers: corsHeaders }) } const response = { @@ -38,9 +33,9 @@ async function handleRequest(request) { } return new Response(JSON.stringify(response, null, 2), { - headers: { - 'Content-Type': 'application/json', - ...corsHeaders - } + headers: corsHeaders }) } + +// Export for wws +module.exports = { handler } diff --git a/chat/index.js b/chat/index.js index 6e5e3e5..45d6058 100644 --- a/chat/index.js +++ b/chat/index.js @@ -1,36 +1,34 @@ // Chat proxy - routes requests to n8n workflow // Path: /chat -addEventListener('fetch', event => { - event.respondWith(handleRequest(event.request)) -}) - -async function handleRequest(request) { +async function handler(request) { const corsHeaders = { 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Methods': 'GET, POST, OPTIONS', 'Access-Control-Allow-Headers': 'Content-Type, Authorization', + 'Content-Type': 'application/json' } if (request.method === 'OPTIONS') { - return new Response(null, { headers: corsHeaders }) + return new Response('', { headers: corsHeaders }) } if (request.method !== 'POST') { return new Response(JSON.stringify({ error: 'Method not allowed' }), { status: 405, - headers: { 'Content-Type': 'application/json', ...corsHeaders } + headers: corsHeaders }) } try { const body = await request.json() - const { message, project_id, user_id, provider = 'zai' } = body + const { message, project_id, user_id, provider } = body + const selectedProvider = provider || 'zai' if (!message) { return new Response(JSON.stringify({ error: 'Message is required' }), { status: 400, - headers: { 'Content-Type': 'application/json', ...corsHeaders } + headers: corsHeaders }) } @@ -39,10 +37,10 @@ async function handleRequest(request) { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ - message, + message: message, project_id: project_id || null, user_id: user_id || null, - provider, + provider: selectedProvider, source: 'wws-proxy', timestamp: new Date().toISOString() }) @@ -53,10 +51,10 @@ async function handleRequest(request) { return new Response(JSON.stringify({ success: true, response: result.response || result, - provider, + provider: selectedProvider, timestamp: new Date().toISOString() }), { - headers: { 'Content-Type': 'application/json', ...corsHeaders } + headers: corsHeaders }) } catch (error) { @@ -65,7 +63,9 @@ async function handleRequest(request) { error: error.message || 'Internal server error' }), { status: 500, - headers: { 'Content-Type': 'application/json', ...corsHeaders } + headers: corsHeaders }) } } + +module.exports = { handler } diff --git a/webhook/index.js b/webhook/index.js index 6085acc..16b4141 100644 --- a/webhook/index.js +++ b/webhook/index.js @@ -1,50 +1,60 @@ // Webhook receiver for external integrations // Path: /webhook -addEventListener('fetch', event => { - event.respondWith(handleRequest(event.request)) -}) - -async function handleRequest(request) { +async function handler(request) { const corsHeaders = { 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Methods': 'GET, POST, OPTIONS', 'Access-Control-Allow-Headers': 'Content-Type, Authorization, X-Webhook-Secret', + 'Content-Type': 'application/json' } if (request.method === 'OPTIONS') { - return new Response(null, { headers: corsHeaders }) + return new Response('', { headers: corsHeaders }) } - const url = new URL(request.url) - const path = url.pathname - - // Log incoming webhook - const logEntry = { - timestamp: new Date().toISOString(), - method: request.method, - path: path, - headers: Object.fromEntries(request.headers.entries()), - query: Object.fromEntries(url.searchParams.entries()) + // GET request - return webhook info + if (request.method === 'GET') { + return new Response(JSON.stringify({ + endpoint: '/webhook', + method: 'POST', + supported_sources: ['gitea', 'stripe', 'supabase', 'default'], + usage: 'POST /webhook?source=gitea with JSON body' + }, null, 2), { + headers: corsHeaders + }) } + // POST request - receive and forward webhook if (request.method === 'POST') { try { + const timestamp = new Date().toISOString() + + // Parse request body + let payload const contentType = request.headers.get('content-type') || '' - let payload if (contentType.includes('application/json')) { payload = await request.json() - } else if (contentType.includes('form')) { - payload = Object.fromEntries(await request.formData()) } else { payload = await request.text() } - logEntry.payload = payload - - // Route based on webhook type/source - const source = url.searchParams.get('source') || 'unknown' + // Get source from query params (wws provides request.url as string) + let source = 'default' + if (request.url && request.url.includes('?')) { + const queryString = request.url.split('?')[1] + if (queryString) { + const params = queryString.split('&') + for (let i = 0; i < params.length; i++) { + const pair = params[i].split('=') + if (pair[0] === 'source' && pair[1]) { + source = decodeURIComponent(pair[1]) + break + } + } + } + } // Forward to appropriate n8n workflow based on source const webhookMap = { @@ -56,44 +66,43 @@ async function handleRequest(request) { const targetUrl = webhookMap[source] || webhookMap['default'] - // Async forward (fire and forget for speed) + // Forward to n8n (fire and forget) fetch(targetUrl, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ - source, - payload, - received_at: logEntry.timestamp, - headers: logEntry.headers + source: source, + payload: payload, + received_at: timestamp }) - }).catch(err => console.error('Forward failed:', err)) + }).catch(function(err) { + console.error('Forward failed:', err) + }) return new Response(JSON.stringify({ received: true, - source, - timestamp: logEntry.timestamp + source: source, + timestamp: timestamp }), { - headers: { 'Content-Type': 'application/json', ...corsHeaders } + headers: corsHeaders }) } catch (error) { return new Response(JSON.stringify({ received: false, - error: error.message + error: error.message || 'Parse error' }), { status: 400, - headers: { 'Content-Type': 'application/json', ...corsHeaders } + headers: corsHeaders }) } } - // GET request - return webhook info - return new Response(JSON.stringify({ - endpoint: '/webhook', - method: 'POST', - supported_sources: ['gitea', 'stripe', 'supabase', 'default'], - usage: 'POST /webhook?source=gitea with JSON body' - }), { - headers: { 'Content-Type': 'application/json', ...corsHeaders } + // Method not allowed + return new Response(JSON.stringify({ error: 'Method not allowed' }), { + status: 405, + headers: corsHeaders }) } + +module.exports = { handler }