Develop complete, testable functions locally and deploy them to see real results. This guide walks you through building functions you can actually test with live URLs.

🌐 Live Testing

Deploy functions and test them with real URLs on your hub

🔄 Data Transformation

See your functions transform data in real-time

📁 Complete Examples

Full function structures with all necessary files

🚀 Deploy & Test

From local development to live URL in minutes

Quick Start: Your First Testable Function

Let’s build a complete function that you can test with a real URL after deployment.

1

Set up your project

# Create project directory
mkdir weather-api && cd weather-api

# Initialize npm and install dependencies
npm init -y
npm install -D typescript @types/node @types/aws-lambda ts-node

# Create project structure
mkdir src lib types
2

Create your function files

import { APIGatewayProxyEvent, APIGatewayProxyResult } from 'aws-lambda';
import { validateCity, transformWeatherData } from './lib/weather';
import { createResponse, handleError } from './lib/utils';

export const handler = async (
  event: APIGatewayProxyEvent
): Promise<APIGatewayProxyResult> => {
  try {
    console.log('Weather API called:', {
      method: event.httpMethod,
      path: event.path,
      query: event.queryStringParameters
    });

    const city = event.queryStringParameters?.city;
    
    // Validate input
    const validation = validateCity(city);
    if (!validation.isValid) {
      return createResponse(400, { 
        error: 'Invalid city name',
        details: validation.errors 
      });
    }

    // Get weather data (simulated for demo)
    const rawWeatherData = await fetchWeatherData(city!);
    
    // Transform the data
    const transformedData = transformWeatherData(rawWeatherData);
    
    return createResponse(200, {
      city: city,
      weather: transformedData,
      timestamp: new Date().toISOString(),
      source: 'Ollie Hub Weather API'
    });
    
  } catch (error) {
    console.error('Weather API error:', error);
    return handleError(error);
  }
};

// Simulate weather API call
async function fetchWeatherData(city: string) {
  // Simulate API delay
  await new Promise(resolve => setTimeout(resolve, 100));
  
  // Return mock weather data
  return {
    temperature: Math.floor(Math.random() * 30) + 10,
    humidity: Math.floor(Math.random() * 40) + 40,
    conditions: ['sunny', 'cloudy', 'rainy', 'windy'][Math.floor(Math.random() * 4)],
    pressure: 1013 + Math.floor(Math.random() * 20) - 10,
    windSpeed: Math.floor(Math.random() * 20),
    rawTimestamp: Date.now()
  };
}
3

Test locally

Create a test file to verify your function works:

test.ts
import { handler } from './index';
import { APIGatewayProxyEvent } from 'aws-lambda';

async function testWeatherAPI() {
  console.log('🧪 Testing Weather API Function\n');
  
  // Test valid city
  const validEvent: Partial<APIGatewayProxyEvent> = {
    httpMethod: 'GET',
    path: '/weather',
    queryStringParameters: { city: 'London' },
    headers: {},
    body: null
  };
  
  console.log('Testing with city: London');
  const result1 = await handler(validEvent as APIGatewayProxyEvent);
  console.log('Status:', result1.statusCode);
  console.log('Response:', JSON.parse(result1.body));
  console.log('\n---\n');
  
  // Test invalid city
  const invalidEvent: Partial<APIGatewayProxyEvent> = {
    httpMethod: 'GET',
    path: '/weather',
    queryStringParameters: { city: 'X' },
    headers: {},
    body: null
  };
  
  console.log('Testing with invalid city: X');
  const result2 = await handler(invalidEvent as APIGatewayProxyEvent);
  console.log('Status:', result2.statusCode);
  console.log('Response:', JSON.parse(result2.body));
  console.log('\n---\n');
  
  // Test missing city
  const missingEvent: Partial<APIGatewayProxyEvent> = {
    httpMethod: 'GET',
    path: '/weather',
    queryStringParameters: null,
    headers: {},
    body: null
  };
  
  console.log('Testing with missing city parameter');
  const result3 = await handler(missingEvent as APIGatewayProxyEvent);
  console.log('Status:', result3.statusCode);
  console.log('Response:', JSON.parse(result3.body));
  
  console.log('\n✅ Local testing completed!');
}

testWeatherAPI().catch(console.error);

Run the test:

npm test
4

Deploy and test live

  1. Upload to Ollie Hub: Zip your function folder and upload it via the web interface
  2. Get your function URL: Copy the URL from your function dashboard
  3. Test with real URLs:
# Replace YOUR_FUNCTION_URL with your actual function URL

# Test valid city
curl "YOUR_FUNCTION_URL?city=Paris"

# Test another city to see different data
curl "YOUR_FUNCTION_URL?city=Tokyo"

# Test error handling
curl "YOUR_FUNCTION_URL?city=X"

# Test missing parameter
curl "YOUR_FUNCTION_URL"

Expected response for Paris:

{
  "city": "Paris",
  "weather": {
    "temp": {
      "celsius": 22,
      "fahrenheit": 72,
      "description": "Mild"
    },
    "humidity": {
      "percentage": 65,
      "level": "Moderate"
    },
    "conditions": {
      "current": "sunny",
      "emoji": "☀️"
    },
    "wind": {
      "speed": 8,
      "description": "Light breeze"
    },
    "comfort": {
      "score": 85,
      "rating": "Excellent"
    }
  },
  "timestamp": "2024-01-15T10:30:00.000Z",
  "source": "Ollie Hub Weather API"
}

Advanced Example: User Data Processor

Build a more complex function that processes and transforms user data:

import { APIGatewayProxyEvent, APIGatewayProxyResult } from 'aws-lambda';
import { validateUserData, processUser, generateUserStats } from './lib/userProcessor';
import { createResponse, handleError } from './lib/utils';

export const handler = async (
  event: APIGatewayProxyEvent
): Promise<APIGatewayProxyResult> => {
  try {
    console.log('User processor called:', {
      method: event.httpMethod,
      path: event.path
    });

    if (event.httpMethod === 'GET') {
      return createResponse(200, {
        message: 'User Data Processor API',
        endpoints: {
          process: 'POST /process - Process user data',
          stats: 'GET /stats?users=number - Generate user statistics'
        },
        example: {
          url: 'POST YOUR_FUNCTION_URL',
          body: {
            name: 'John Doe',
            email: 'john@example.com',
            age: 28,
            interests: ['technology', 'sports'],
            location: 'New York'
          }
        }
      });
    }

    if (event.httpMethod === 'POST') {
      const userData = JSON.parse(event.body || '{}');
      
      // Validate user data
      const validation = validateUserData(userData);
      if (!validation.isValid) {
        return createResponse(400, {
          error: 'Invalid user data',
          details: validation.errors
        });
      }

      // Process and transform user data
      const processedUser = processUser(userData);
      
      return createResponse(200, {
        original: userData,
        processed: processedUser,
        transformation: {
          added: ['id', 'slug', 'category', 'score', 'recommendations'],
          computed: ['ageGroup', 'riskLevel', 'primaryInterest'],
          formatted: ['email', 'name', 'location']
        }
      });
    }

    // Handle stats endpoint
    if (event.path?.includes('stats')) {
      const userCount = parseInt(event.queryStringParameters?.users || '10');
      const stats = generateUserStats(userCount);
      
      return createResponse(200, {
        stats,
        generated: userCount,
        timestamp: new Date().toISOString()
      });
    }

    return createResponse(405, { error: 'Method not allowed' });
    
  } catch (error) {
    return handleError(error);
  }
};

Test the User Processor

test-user-processor.ts
import { handler } from './index';
import { APIGatewayProxyEvent } from 'aws-lambda';

async function testUserProcessor() {
  console.log('🧪 Testing User Data Processor\n');
  
  // Test API info
  const infoEvent: Partial<APIGatewayProxyEvent> = {
    httpMethod: 'GET',
    path: '/',
    queryStringParameters: null,
    headers: {},
    body: null
  };
  
  console.log('1. Getting API information:');
  const infoResult = await handler(infoEvent as APIGatewayProxyEvent);
  console.log('Response:', JSON.parse(infoResult.body));
  console.log('\n---\n');
  
  // Test user processing
  const userData = {
    name: 'Alice Johnson',
    email: 'alice@example.com',
    age: 28,
    interests: ['technology', 'travel', 'photography'],
    location: 'San Francisco'
  };
  
  const processEvent: Partial<APIGatewayProxyEvent> = {
    httpMethod: 'POST',
    path: '/process',
    body: JSON.stringify(userData),
    headers: { 'Content-Type': 'application/json' },
    queryStringParameters: null
  };
  
  console.log('2. Processing user data:');
  console.log('Input:', userData);
  const processResult = await handler(processEvent as APIGatewayProxyEvent);
  console.log('Output:', JSON.parse(processResult.body));
  console.log('\n---\n');
  
  // Test stats generation
  const statsEvent: Partial<APIGatewayProxyEvent> = {
    httpMethod: 'GET',
    path: '/stats',
    queryStringParameters: { users: '100' },
    headers: {},
    body: null
  };
  
  console.log('3. Generating user statistics:');
  const statsResult = await handler(statsEvent as APIGatewayProxyEvent);
  console.log('Stats:', JSON.parse(statsResult.body));
  
  console.log('\n✅ All tests completed!');
}

testUserProcessor().catch(console.error);

Real-World Data Transformation Examples

Deployment Checklist

1

Local testing passes

✅ All functions run without errors locally
✅ Data transformation works as expected
✅ Error handling catches edge cases
✅ TypeScript compiles without warnings

2

Function structure is correct

index.ts exists with exported handler
package.json includes all dependencies
✅ Helper files are properly structured
✅ No sensitive data in source code

3

Upload and configure

✅ Function uploaded to Ollie Hub
✅ Environment variables configured
✅ Function type set correctly (Request/Task/Response)
✅ Memory and timeout settings appropriate

4

Live testing

✅ Function URL accessible
✅ Data transformation works on live data
✅ Error responses are user-friendly
✅ Performance is acceptable

Next Steps

Ready to Build? Start with the Weather API example above - it’s designed to work immediately and show you real data transformation. You’ll have a working function with a testable URL in under 10 minutes!