Edge Functions API - arilonUK/iotagentmesh GitHub Wiki

Edge Functions API

Edge Functions provide serverless compute capabilities for custom business logic, integrations, and real-time processing within the IoT Agent Mesh platform. These TypeScript functions run globally at the edge for low latency.

Overview

Edge Functions enable:

  • Custom business logic processing
  • Third-party service integrations
  • Webhook handling and event processing
  • Real-time data transformation
  • Automated alert processing and notifications
  • Custom API endpoints with advanced routing

Base Endpoint

/functions/v1/

Authentication

Edge Functions support multiple authentication methods:

JWT Authentication (Recommended):

Authorization: Bearer YOUR_JWT_TOKEN

API Key Authentication:

Authorization: Bearer YOUR_API_KEY

No Authentication (Webhooks only): Functions can be deployed with --no-verify-jwt for webhook endpoints.


Available Edge Functions

Device Data Processing

Process and validate telemetry data before storage.

POST /functions/v1/process-device-data

Request Body

{
  "agent_id": "agent_01H8K2M3N4P5Q6R7S8T9U0V1W2",
  "raw_data": {
    "temp": "23.5",
    "hum": "65.2",
    "batt": "87",
    "sig": "-65"
  },
  "metadata": {
    "firmware_version": "1.4.2",
    "timestamp": "2024-07-23T16:45:00Z"
  }
}

Response

{
  "processed_data": {
    "temperature": 23.5,
    "humidity": 65.2,
    "battery_level": 87,
    "signal_strength": -65
  },
  "validation_results": {
    "valid": true,
    "warnings": [],
    "errors": []
  },
  "transformations_applied": [
    "string_to_number",
    "field_mapping",
    "range_validation"
  ],
  "stored": true,
  "telemetry_id": "01H8K3L4M5N6O7P8Q9R0S1T2U3V4"
}

Code Examples

JavaScript/TypeScript:

const response = await supabase.functions.invoke('process-device-data', {
  body: {
    agent_id: 'agent_01H8K2M3N4P5Q6R7S8T9U0V1W2',
    raw_data: {
      temp: '23.5',
      hum: '65.2',
      batt: '87'
    },
    metadata: {
      firmware_version: '1.4.2'
    }
  }
})

console.log('Processed data:', response.data)

Python:

import requests

response = requests.post( 'https://your-project-id.supabase.co/functions/v1/process-device-data', headers={ 'Authorization': f'Bearer {jwt_token}', 'Content-Type': 'application/json' }, json={ 'agent_id': 'agent_01H8K2M3N4P5Q6R7S8T9U0V1W2', 'raw_data': { 'temp': '23.5', 'hum': '65.2', 'batt': '87' } } )

data = response.json()


Webhook Handler

Generic webhook handler for external service integrations.

POST /functions/v1/webhook-handler

Request Headers

X-Webhook-Source: stripe|github|custom
X-Webhook-Signature: sha256=signature_hash
Content-Type: application/json

Request Body (Example - Stripe)

{
  "id": "evt_1234567890",
  "object": "event",
  "type": "invoice.payment_succeeded",
  "data": {
    "object": {
      "id": "in_1234567890",
      "customer": "cus_organization_123",
      "amount_paid": 2999,
      "status": "paid"
    }
  },
  "created": 1721750400
}

Response

{
  "received": true,
  "event_type": "invoice.payment_succeeded",
  "processed": true,
  "actions_taken": [
    "updated_subscription_status",
    "sent_confirmation_email",
    "updated_organization_limits"
  ],
  "processing_time_ms": 245
}

Code Examples

Webhook Integration:

// Configure webhook in external service to POST to:
// https://your-project-id.supabase.co/functions/v1/webhook-handler

// The function automatically handles: // - Signature verification // - Event deduplication // - Retry logic // - Database updates


Alert Notification Dispatcher

Process and send alert notifications through multiple channels.

POST /functions/v1/send-alert-notification

Request Body

{
  "alert_id": "alert_01H8K3L4M5N6O7P8Q9R0S1T2U3V4",
  "agent_id": "agent_01H8K2M3N4P5Q6R7S8T9U0V1W2",
  "severity": "high",
  "message": "Temperature exceeds threshold",
  "data": {
    "current_temperature": 42.5,
    "threshold": 35.0,
    "location": "warehouse-a"
  },
  "notification_channels": ["email", "sms", "webhook"],
  "recipients": [
    {
      "type": "user",
      "id": "user_01H8K2M3N4P5Q6R7S8T9U0V1W2"
    },
    {
      "type": "role",
      "role": "admin"
    }
  ]
}

Response

{
  "alert_id": "alert_01H8K3L4M5N6O7P8Q9R0S1T2U3V4",
  "notifications_sent": 3,
  "results": [
    {
      "channel": "email",
      "recipient": "[email protected]",
      "status": "sent",
      "sent_at": "2024-07-23T16:45:01Z"
    },
    {
      "channel": "sms",
      "recipient": "+1-555-0123",
      "status": "sent",
      "sent_at": "2024-07-23T16:45:02Z"
    },
    {
      "channel": "webhook",
      "recipient": "https://company.com/alerts",
      "status": "sent",
      "sent_at": "2024-07-23T16:45:03Z"
    }
  ],
  "processing_time_ms": 1250
}

Code Examples

JavaScript/TypeScript:

const response = await supabase.functions.invoke('send-alert-notification', {
  body: {
    alert_id: 'alert_01H8K3L4M5N6O7P8Q9R0S1T2U3V4',
    agent_id: 'agent_01H8K2M3N4P5Q6R7S8T9U0V1W2',
    severity: 'high',
    message: 'Temperature exceeds threshold',
    data: {
      current_temperature: 42.5,
      threshold: 35.0,
      location: 'warehouse-a'
    },
    notification_channels: ['email', 'sms', 'webhook']
  }
})

console.log('Notifications sent:', response.data.notifications_sent)


Data Aggregation Engine

Perform complex data aggregations and analytics.

POST /functions/v1/data-aggregation

Request Body

{
  "aggregation_type": "time_series",
  "agents": ["agent_01H8K2M3N4P5Q6R7S8T9U0V1W2", "agent_02H8K2M3N4P5Q6R7S8T9U0V1W3"],
  "fields": [
    {
      "name": "temperature",
      "operations": ["avg", "min", "max", "stddev"]
    },
    {
      "name": "humidity",
      "operations": ["avg"]
    }
  ],
  "time_range": {
    "start": "2024-07-23T00:00:00Z",
    "end": "2024-07-23T23:59:59Z"
  },
  "interval": "1h",
  "filters": {
    "temperature": {
      "min": -50,
      "max": 100
    }
  },
  "output_format": "json"
}

Response

{
  "aggregation_id": "agg_01H8K3L4M5N6O7P8Q9R0S1T2U3V4",
  "agents_processed": 2,
  "time_range": {
    "start": "2024-07-23T00:00:00Z",
    "end": "2024-07-23T23:59:59Z"
  },
  "interval": "1h",
  "data": [
    {
      "timestamp": "2024-07-23T00:00:00Z",
      "temperature": {
        "avg": 22.3,
        "min": 19.8,
        "max": 24.7,
        "stddev": 1.2
      },
      "humidity": {
        "avg": 65.4
      },
      "sample_count": 120
    },
    {
      "timestamp": "2024-07-23T01:00:00Z",
      "temperature": {
        "avg": 22.1,
        "min": 19.5,
        "max": 24.3,
        "stddev": 1.1
      },
      "humidity": {
        "avg": 66.1
      },
      "sample_count": 120
    }
  ],
  "summary": {
    "total_samples": 2880,
    "processing_time_ms": 450,
    "cache_hit_rate": 0.85
  }
}

Code Examples

JavaScript/TypeScript:

const response = await supabase.functions.invoke('data-aggregation', {
  body: {
    aggregation_type: 'time_series',
    agents: ['agent_01H8K2M3N4P5Q6R7S8T9U0V1W2'],
    fields: [
      {
        name: 'temperature',
        operations: ['avg', 'min', 'max']
      }
    ],
    time_range: {
      start: '2024-07-23T00:00:00Z',
      end: '2024-07-23T23:59:59Z'
    },
    interval: '1h'
  }
})

console.log('Aggregated data:', response.data.data)


Report Generator

Generate comprehensive reports with data visualization.

POST /functions/v1/generate-report

Request Body

{
  "report_type": "organization_summary",
  "organization_id": "org_01H8K2M3N4P5Q6R7S8T9U0V1W2",
  "time_period": {
    "start": "2024-07-01T00:00:00Z",
    "end": "2024-07-31T23:59:59Z"
  },
  "sections": [
    "agent_overview",
    "telemetry_summary",
    "alert_analysis",
    "performance_metrics"
  ],
  "format": "pdf",
  "include_charts": true,
  "recipients": ["[email protected]"]
}

Response

{
  "report_id": "report_01H8K3L4M5N6O7P8Q9R0S1T2U3V4",
  "status": "generated",
  "format": "pdf",
  "file_size": "2.3MB",
  "download_url": "https://your-project-id.supabase.co/storage/v1/object/reports/report_01H8K3L4M5N6O7P8Q9R0S1T2U3V4.pdf",
  "expires_at": "2024-08-23T16:45:00Z",
  "sections_included": [
    "agent_overview",
    "telemetry_summary", 
    "alert_analysis",
    "performance_metrics"
  ],
  "generation_time_ms": 3500,
  "email_sent": true
}

External API Integration

Integrate with third-party services and APIs.

POST /functions/v1/external-integration

Request Body

{
  "service": "weather_api",
  "action": "get_weather_data",
  "parameters": {
    "location": "warehouse-a",
    "coordinates": {
      "lat": 40.7128,
      "lon": -74.0060
    }
  },
  "agent_id": "agent_01H8K2M3N4P5Q6R7S8T9U0V1W2",
  "correlation_fields": ["temperature", "humidity", "pressure"]
}

Response

{
  "service": "weather_api",
  "status": "success",
  "data": {
    "temperature": 24.3,
    "humidity": 68.5,
    "pressure": 1013.2,
    "wind_speed": 5.2,
    "conditions": "partly_cloudy"
  },
  "correlation_analysis": {
    "temperature_correlation": 0.87,
    "humidity_correlation": 0.72,
    "pressure_correlation": 0.93
  },
  "recommendations": [
    "External temperature is consistent with sensor readings",
    "Consider calibrating humidity sensor - 3.3% deviation",
    "Pressure readings are highly accurate"
  ],
  "cached_until": "2024-07-23T17:45:00Z"
}

Custom Edge Functions

Creating Custom Functions

You can deploy custom Edge Functions for specific business logic:

Function Structure

// supabase/functions/custom-logic/index.ts
import { serve } from 'https://deno.land/[email protected]/http/server.ts'
import { createClient } from 'https://esm.sh/@supabase/supabase-js@2'

const corsHeaders = { 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type', }

serve(async (req) => { // Handle CORS preflight requests if (req.method === 'OPTIONS') { return new Response('ok', { headers: corsHeaders }) }

try { // Initialize Supabase client const supabase = createClient( Deno.env.get('SUPABASE_URL') ?? '', Deno.env.get('SUPABASE_SERVICE_ROLE_KEY') ?? '' )

// Get request body
const { agent_id, custom_data } = await req.json()

// Your custom business logic here
const result = await processCustomLogic(agent_id, custom_data, supabase)

return new Response(
  JSON.stringify(result),
  {
    headers: { ...corsHeaders, 'Content-Type': 'application/json' },
    status: 200,
  }
)

} catch (error) { return new Response( JSON.stringify({ error: error.message }), { headers: { ...corsHeaders, 'Content-Type': 'application/json' }, status: 400, } ) } })

async function processCustomLogic(agentId: string, data: any, supabase: any) { // Implement your custom logic const { data: agent } = await supabase .from('agents') .select('*') .eq('id', agentId) .single()

// Process data and return results return { agent_id: agentId, processed: true, result: 'Custom processing completed' } }

Deployment

# Deploy the function
supabase functions deploy custom-logic

Deploy with specific permissions

supabase functions deploy custom-logic --no-verify-jwt

Usage

const response = await supabase.functions.invoke('custom-logic', {
  body: {
    agent_id: 'agent_123',
    custom_data: {
      type: 'sensor_calibration',
      values: [1, 2, 3, 4, 5]
    }
  }
})

Function Routing

HTTP Method Routing

Edge Functions can handle multiple HTTP methods:

serve(async (req) => {
  const url = new URL(req.url)
  const path = url.pathname
  const method = req.method

switch (method) { case 'GET': return handleGet(path, url.searchParams) case 'POST': return handlePost(path, await req.json()) case 'PUT': return handlePut(path, await req.json()) case 'DELETE': return handleDelete(path) default: return new Response('Method not allowed', { status: 405 }) } })

Path-based Routing

import { Hono } from 'jsr:@hono/hono'

const app = new Hono()

app.get('/agents/:id', async (c) => { const agentId = c.req.param('id') // Handle GET /agents/:id })

app.post('/agents/:id/telemetry', async (c) => { const agentId = c.req.param('id') const telemetryData = await c.req.json() // Handle POST /agents/:id/telemetry })

Deno.serve(app.fetch)


Environment Variables

Available Variables

Edge Functions have access to these environment variables:

Variable Description
SUPABASE_URL Your Supabase project URL
SUPABASE_ANON_KEY Public anonymous key
SUPABASE_SERVICE_ROLE_KEY Service role key (full access)
SUPABASE_DB_URL Direct database connection URL

Rate limits are per authenticated user per organization, except for webhook handlers which are per IP address.

# Edge Functions API

Edge Functions provide serverless compute capabilities for custom business logic, integrations, and real-time processing within the IoT Agent Mesh platform. These TypeScript functions run globally at the edge for low latency.

Overview

Edge Functions enable:

  • Custom business logic processing
  • Third-party service integrations
  • Webhook handling and event processing
  • Real-time data transformation
  • Automated alert processing and notifications
  • Custom API endpoints with advanced routing

Base Endpoint

/functions/v1/

Authentication

Edge Functions support multiple authentication methods:

JWT Authentication (Recommended):

Authorization: Bearer YOUR_JWT_TOKEN

API Key Authentication:

Authorization: Bearer YOUR_API_KEY

No Authentication (Webhooks only): Functions can be deployed with --no-verify-jwt for webhook endpoints.


Available Edge Functions

Device Data Processing

Process and validate telemetry data before storage.

POST /functions/v1/process-device-data

Request Body

{
  "agent_id": "agent_01H8K2M3N4P5Q6R7S8T9U0V1W2",
  "raw_data": {
    "temp": "23.5",
    "hum": "65.2",
    "batt": "87",
    "sig": "-65"
  },
  "metadata": {
    "firmware_version": "1.4.2",
    "timestamp": "2024-07-23T16:45:00Z"
  }
}

Response

{
  "processed_data": {
    "temperature": 23.5,
    "humidity": 65.2,
    "battery_level": 87,
    "signal_strength": -65
  },
  "validation_results": {
    "valid": true,
    "warnings": [],
    "errors": []
  },
  "transformations_applied": [
    "string_to_number",
    "field_mapping",
    "range_validation"
  ],
  "stored": true,
  "telemetry_id": "01H8K3L4M5N6O7P8Q9R0S1T2U3V4"
}

Code Examples

JavaScript/TypeScript:

const response = await supabase.functions.invoke('process-device-data', {
  body: {
    agent_id: 'agent_01H8K2M3N4P5Q6R7S8T9U0V1W2',
    raw_data: {
      temp: '23.5',
      hum: '65.2',
      batt: '87'
    },
    metadata: {
      firmware_version: '1.4.2'
    }
  }
})

console.log('Processed data:', response.data)

Python:

import requests

response = requests.post(
    'https://your-project-id.supabase.co/functions/v1/process-device-data',
    headers={
        'Authorization': f'Bearer {jwt_token}',
        'Content-Type': 'application/json'
    },
    json={
        'agent_id': 'agent_01H8K2M3N4P5Q6R7S8T9U0V1W2',
        'raw_data': {
            'temp': '23.5',
            'hum': '65.2',
            'batt': '87'
        }
    }
)

data = response.json()

Webhook Handler

Generic webhook handler for external service integrations.

POST /functions/v1/webhook-handler

Request Headers

X-Webhook-Source: stripe|github|custom
X-Webhook-Signature: sha256=signature_hash
Content-Type: application/json

Request Body (Example - Stripe)

{
  "id": "evt_1234567890",
  "object": "event",
  "type": "invoice.payment_succeeded",
  "data": {
    "object": {
      "id": "in_1234567890",
      "customer": "cus_organization_123",
      "amount_paid": 2999,
      "status": "paid"
    }
  },
  "created": 1721750400
}

Response

{
  "received": true,
  "event_type": "invoice.payment_succeeded",
  "processed": true,
  "actions_taken": [
    "updated_subscription_status",
    "sent_confirmation_email",
    "updated_organization_limits"
  ],
  "processing_time_ms": 245
}

Code Examples

Webhook Integration:

// Configure webhook in external service to POST to:
// https://your-project-id.supabase.co/functions/v1/webhook-handler

// The function automatically handles:
// - Signature verification
// - Event deduplication
// - Retry logic
// - Database updates

Alert Notification Dispatcher

Process and send alert notifications through multiple channels.

POST /functions/v1/send-alert-notification

Request Body

{
  "alert_id": "alert_01H8K3L4M5N6O7P8Q9R0S1T2U3V4",
  "agent_id": "agent_01H8K2M3N4P5Q6R7S8T9U0V1W2",
  "severity": "high",
  "message": "Temperature exceeds threshold",
  "data": {
    "current_temperature": 42.5,
    "threshold": 35.0,
    "location": "warehouse-a"
  },
  "notification_channels": ["email", "sms", "webhook"],
  "recipients": [
    {
      "type": "user",
      "id": "user_01H8K2M3N4P5Q6R7S8T9U0V1W2"
    },
    {
      "type": "role",
      "role": "admin"
    }
  ]
}

Response

{
  "alert_id": "alert_01H8K3L4M5N6O7P8Q9R0S1T2U3V4",
  "notifications_sent": 3,
  "results": [
    {
      "channel": "email",
      "recipient": "[email protected]",
      "status": "sent",
      "sent_at": "2024-07-23T16:45:01Z"
    },
    {
      "channel": "sms",
      "recipient": "+1-555-0123",
      "status": "sent",
      "sent_at": "2024-07-23T16:45:02Z"
    },
    {
      "channel": "webhook",
      "recipient": "https://company.com/alerts",
      "status": "sent",
      "sent_at": "2024-07-23T16:45:03Z"
    }
  ],
  "processing_time_ms": 1250
}

Code Examples

JavaScript/TypeScript:

const response = await supabase.functions.invoke('send-alert-notification', {
  body: {
    alert_id: 'alert_01H8K3L4M5N6O7P8Q9R0S1T2U3V4',
    agent_id: 'agent_01H8K2M3N4P5Q6R7S8T9U0V1W2',
    severity: 'high',
    message: 'Temperature exceeds threshold',
    data: {
      current_temperature: 42.5,
      threshold: 35.0,
      location: 'warehouse-a'
    },
    notification_channels: ['email', 'sms', 'webhook']
  }
})

console.log('Notifications sent:', response.data.notifications_sent)

Data Aggregation Engine

Perform complex data aggregations and analytics.

POST /functions/v1/data-aggregation

Request Body

{
  "aggregation_type": "time_series",
  "agents": ["agent_01H8K2M3N4P5Q6R7S8T9U0V1W2", "agent_02H8K2M3N4P5Q6R7S8T9U0V1W3"],
  "fields": [
    {
      "name": "temperature",
      "operations": ["avg", "min", "max", "stddev"]
    },
    {
      "name": "humidity",
      "operations": ["avg"]
    }
  ],
  "time_range": {
    "start": "2024-07-23T00:00:00Z",
    "end": "2024-07-23T23:59:59Z"
  },
  "interval": "1h",
  "filters": {
    "temperature": {
      "min": -50,
      "max": 100
    }
  },
  "output_format": "json"
}

Response

{
  "aggregation_id": "agg_01H8K3L4M5N6O7P8Q9R0S1T2U3V4",
  "agents_processed": 2,
  "time_range": {
    "start": "2024-07-23T00:00:00Z",
    "end": "2024-07-23T23:59:59Z"
  },
  "interval": "1h",
  "data": [
    {
      "timestamp": "2024-07-23T00:00:00Z",
      "temperature": {
        "avg": 22.3,
        "min": 19.8,
        "max": 24.7,
        "stddev": 1.2
      },
      "humidity": {
        "avg": 65.4
      },
      "sample_count": 120
    },
    {
      "timestamp": "2024-07-23T01:00:00Z",
      "temperature": {
        "avg": 22.1,
        "min": 19.5,
        "max": 24.3,
        "stddev": 1.1
      },
      "humidity": {
        "avg": 66.1
      },
      "sample_count": 120
    }
  ],
  "summary": {
    "total_samples": 2880,
    "processing_time_ms": 450,
    "cache_hit_rate": 0.85
  }
}

Code Examples

JavaScript/TypeScript:

const response = await supabase.functions.invoke('data-aggregation', {
  body: {
    aggregation_type: 'time_series',
    agents: ['agent_01H8K2M3N4P5Q6R7S8T9U0V1W2'],
    fields: [
      {
        name: 'temperature',
        operations: ['avg', 'min', 'max']
      }
    ],
    time_range: {
      start: '2024-07-23T00:00:00Z',
      end: '2024-07-23T23:59:59Z'
    },
    interval: '1h'
  }
})

console.log('Aggregated data:', response.data.data)

Report Generator

Generate comprehensive reports with data visualization.

POST /functions/v1/generate-report

Request Body

{
  "report_type": "organization_summary",
  "organization_id": "org_01H8K2M3N4P5Q6R7S8T9U0V1W2",
  "time_period": {
    "start": "2024-07-01T00:00:00Z",
    "end": "2024-07-31T23:59:59Z"
  },
  "sections": [
    "agent_overview",
    "telemetry_summary",
    "alert_analysis",
    "performance_metrics"
  ],
  "format": "pdf",
  "include_charts": true,
  "recipients": ["[email protected]"]
}

Response

{
  "report_id": "report_01H8K3L4M5N6O7P8Q9R0S1T2U3V4",
  "status": "generated",
  "format": "pdf",
  "file_size": "2.3MB",
  "download_url": "https://your-project-id.supabase.co/storage/v1/object/reports/report_01H8K3L4M5N6O7P8Q9R0S1T2U3V4.pdf",
  "expires_at": "2024-08-23T16:45:00Z",
  "sections_included": [
    "agent_overview",
    "telemetry_summary", 
    "alert_analysis",
    "performance_metrics"
  ],
  "generation_time_ms": 3500,
  "email_sent": true
}

External API Integration

Integrate with third-party services and APIs.

POST /functions/v1/external-integration

Request Body

{
  "service": "weather_api",
  "action": "get_weather_data",
  "parameters": {
    "location": "warehouse-a",
    "coordinates": {
      "lat": 40.7128,
      "lon": -74.0060
    }
  },
  "agent_id": "agent_01H8K2M3N4P5Q6R7S8T9U0V1W2",
  "correlation_fields": ["temperature", "humidity", "pressure"]
}

Response

{
  "service": "weather_api",
  "status": "success",
  "data": {
    "temperature": 24.3,
    "humidity": 68.5,
    "pressure": 1013.2,
    "wind_speed": 5.2,
    "conditions": "partly_cloudy"
  },
  "correlation_analysis": {
    "temperature_correlation": 0.87,
    "humidity_correlation": 0.72,
    "pressure_correlation": 0.93
  },
  "recommendations": [
    "External temperature is consistent with sensor readings",
    "Consider calibrating humidity sensor - 3.3% deviation",
    "Pressure readings are highly accurate"
  ],
  "cached_until": "2024-07-23T17:45:00Z"
}

Custom Edge Functions

Creating Custom Functions

You can deploy custom Edge Functions for specific business logic:

Function Structure

// supabase/functions/custom-logic/index.ts
import { serve } from 'https://deno.land/[email protected]/http/server.ts'
import { createClient } from 'https://esm.sh/@supabase/supabase-js@2'

const corsHeaders = {
  'Access-Control-Allow-Origin': '*',
  'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type',
}

serve(async (req) => {
  // Handle CORS preflight requests
  if (req.method === 'OPTIONS') {
    return new Response('ok', { headers: corsHeaders })
  }

  try {
    // Initialize Supabase client
    const supabase = createClient(
      Deno.env.get('SUPABASE_URL') ?? '',
      Deno.env.get('SUPABASE_SERVICE_ROLE_KEY') ?? ''
    )

    // Get request body
    const { agent_id, custom_data } = await req.json()

    // Your custom business logic here
    const result = await processCustomLogic(agent_id, custom_data, supabase)

    return new Response(
      JSON.stringify(result),
      {
        headers: { ...corsHeaders, 'Content-Type': 'application/json' },
        status: 200,
      }
    )
  } catch (error) {
    return new Response(
      JSON.stringify({ error: error.message }),
      {
        headers: { ...corsHeaders, 'Content-Type': 'application/json' },
        status: 400,
      }
    )
  }
})

async function processCustomLogic(agentId: string, data: any, supabase: any) {
  // Implement your custom logic
  const { data: agent } = await supabase
    .from('agents')
    .select('*')
    .eq('id', agentId)
    .single()

  // Process data and return results
  return {
    agent_id: agentId,
    processed: true,
    result: 'Custom processing completed'
  }
}

Deployment

# Deploy the function
supabase functions deploy custom-logic

# Deploy with specific permissions
supabase functions deploy custom-logic --no-verify-jwt

Usage

const response = await supabase.functions.invoke('custom-logic', {
  body: {
    agent_id: 'agent_123',
    custom_data: {
      type: 'sensor_calibration',
      values: [1, 2, 3, 4, 5]
    }
  }
})

Function Routing

HTTP Method Routing

Edge Functions can handle multiple HTTP methods:

serve(async (req) => {
  const url = new URL(req.url)
  const path = url.pathname
  const method = req.method

  switch (method) {
    case 'GET':
      return handleGet(path, url.searchParams)
    case 'POST':
      return handlePost(path, await req.json())
    case 'PUT':
      return handlePut(path, await req.json())
    case 'DELETE':
      return handleDelete(path)
    default:
      return new Response('Method not allowed', { status: 405 })
  }
})

Path-based Routing

import { Hono } from 'jsr:@hono/hono'

const app = new Hono()

app.get('/agents/:id', async (c) => {
  const agentId = c.req.param('id')
  // Handle GET /agents/:id
})

app.post('/agents/:id/telemetry', async (c) => {
  const agentId = c.req.param('id')
  const telemetryData = await c.req.json()
  // Handle POST /agents/:id/telemetry
})

Deno.serve(app.fetch)

Environment Variables

Available Variables

Edge Functions have access to these environment variables:

Variable Description
SUPABASE_URL Your Supabase project URL
SUPABASE_ANON_KEY Public anonymous key
SUPABASE_SERVICE_ROLE_KEY Service role key (full access)
SUPABASE_DB_URL Direct database connection URL

Custom Environment Variables

// Access custom environment variables
const API_KEY = Deno.env.get('THIRD_PARTY_API_KEY')
const WEBHOOK_SECRET = Deno.env.get('WEBHOOK_SECRET')
const SMTP_CONFIG = {
  host: Deno.env.get('SMTP_HOST'),
  port: Deno.env.get('SMTP_PORT'),
  user: Deno.env.get('SMTP_USER'),
  pass: Deno.env.get('SMTP_PASS')
}

Error Handling

Standard Error Response

{
  "error": {
    "code": "FUNCTION_ERROR",
    "message": "Error processing request",
    "details": {
      "function": "process-device-data",
      "timestamp": "2024-07-23T16:45:00Z",
      "request_id": "req_01H8K3L4M5N6O7P8Q9R0S1T2U3V4"
    }
  },
  "status": 500
}

Error Handling in Functions

serve(async (req) => {
  try {
    // Function logic here
    return new Response(JSON.stringify(result), {
      headers: { 'Content-Type': 'application/json' },
      status: 200
    })
  } catch (error) {
    console.error('Function error:', error)
    
    return new Response(JSON.stringify({
      error: {
        code: 'FUNCTION_ERROR',
        message: error.message,
        details: {
          function: 'function-name',
          timestamp: new Date().toISOString()
        }
      }
    }), {
      headers: { 'Content-Type': 'application/json' },
      status: 500
    })
  }
})

Performance Optimization

Best Practices

  1. Cold Start Optimization:

    // Initialize expensive resources outside the serve handler
    const supabase = createClient(url, key)
    const httpClient = new HTTPClient()
    
    serve(async (req) => {
      // Use pre-initialized resources
    })
  2. Connection Pooling:

    // Reuse database connections
    const dbPool = new Pool({
      connectionString: Deno.env.get('SUPABASE_DB_URL'),
      max: 10
    })
  3. Caching:

    const cache = new Map()
    
    async function getCachedData(key: string) {
      if (cache.has(key)) {
        return cache.get(key)
      }
      
      const data = await fetchData(key)
      cache.set(key, data)
      return data
    }
  4. Streaming Responses:

    serve(async (req) => {
      const stream = new ReadableStream({
        start(controller) {
          // Stream large datasets
          processDataInChunks((chunk) => {
            controller.enqueue(chunk)
          })
        }
      })
      
      return new Response(stream, {
        headers: { 'Content-Type': 'application/json' }
      })
    })

Monitoring and Metrics

// Add performance monitoring
const startTime = performance.now()

// Function logic here

const endTime = performance.now()
const executionTime = endTime - startTime

console.log(`Function executed in ${executionTime}ms`)

// Log metrics for monitoring
await logMetrics({
  function_name: 'process-device-data',
  execution_time_ms: executionTime,
  memory_usage: Deno.memoryUsage(),
  timestamp: new Date().toISOString()
})

Testing Edge Functions

Local Testing

# Start local Supabase stack
supabase start

# Your function is available at:
# http://localhost:54321/functions/v1/your-function-name

# Test with curl
curl -X POST http://localhost:54321/functions/v1/process-device-data \
  -H "Authorization: Bearer YOUR_LOCAL_JWT" \
  -H "Content-Type: application/json" \
  -d '{"agent_id": "test-agent", "data": {"temp": 25}}'

Unit Testing

// tests/process-device-data.test.ts
import { assertEquals } from 'https://deno.land/[email protected]/testing/asserts.ts'
import { processDeviceData } from '../functions/process-device-data/index.ts'

Deno.test('should process device data correctly', async () => {
  const input = {
    agent_id: 'test-agent',
    raw_data: { temp: '25.5', hum: '60' }
  }
  
  const result = await processDeviceData(input)
  
  assertEquals(result.processed_data.temperature, 25.5)
  assertEquals(result.processed_data.humidity, 60)
  assertEquals(result.validation_results.valid, true)
})

Integration Testing

// Test with real Supabase instance
const supabase = createClient(TEST_URL, TEST_KEY)

const response = await supabase.functions.invoke('process-device-data', {
  body: {
    agent_id: 'test-agent',
    raw_data: { temp: '25.5' }
  }
})

assertEquals(response.status, 200)
assertEquals(response.data.processed_data.temperature, 25.5)

Security Considerations

Authentication Validation

import { createClient } from '@supabase/supabase-js'

async function validateAuth(req: Request) {
  const authHeader = req.headers.get('Authorization')
  if (!authHeader) {
    throw new Error('Missing authorization header')
  }

  const token = authHeader.replace('Bearer ', '')
  const supabase = createClient(url, anonKey)
  
  const { data: { user }, error } = await supabase.auth.getUser(token)
  if (error || !user) {
    throw new Error('Invalid token')
  }
  
  return user
}

Input Validation

import { z } from 'https://deno.land/x/zod/mod.ts'

const inputSchema = z.object({
  agent_id: z.string().min(1),
  data: z.object({
    temperature: z.number().min(-50).max(100)
  })
})

serve(async (req) => {
  try {
    const body = await req.json()
    const validatedInput = inputSchema.parse(body)
    
    // Process validated input
  } catch (error) {
    return new Response(JSON.stringify({
      error: 'Invalid input',
      details: error.issues
    }), { status: 400 })
  }
})

Rate Limiting

const requestCounts = new Map()

function rateLimit(identifier: string, limit: number, window: number) {
  const now = Date.now()
  const windowStart = now - window
  
  const requests = requestCounts.get(identifier) || []
  const recentRequests = requests.filter(time => time > windowStart)
  
  if (recentRequests.length >= limit) {
    throw new Error('Rate limit exceeded')
  }
  
  recentRequests.push(now)
  requestCounts.set(identifier, recentRequests)
}

Related Resources

  • [Telemetry API](API-Telemetry.md) - Data processing and storage
  • [Alerts API](API-Alerts.md) - Alert processing and notifications
  • [Webhooks API](API-Webhooks.md) - Webhook configuration and handling
  • [Authentication API](API-Authentication.md) - Function authentication methods

Rate Limits

Function Type Rate Limit Window
Data Processing 1000 requests 1 minute
Webhook Handlers 2000 requests 1 minute
Report Generation 10 requests 1 hour
External Integrations 100 requests 1 minute
Custom Functions 500 requests 1 minute

Rate limits are per authenticated user per organization, except for webhook handlers which are per IP address.

⚠️ **GitHub.com Fallback** ⚠️