Fix wws runtime compatibility - use module.exports pattern

- 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 <noreply@anthropic.com>
This commit is contained in:
2025-12-15 05:56:18 +01:00
parent 9d83a9d2f0
commit 02d32536a0
3 changed files with 72 additions and 68 deletions

View File

@@ -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 }

View File

@@ -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 }

View File

@@ -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(function(err) {
console.error('Forward failed:', err)
})
}).catch(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 }