Docs/Development

Server Functions

Custom TypeScript/JavaScript code that runs on the server for business logic.

Server Functions

Overview

Server Functions are custom TypeScript/JavaScript code that runs on the server. They allow you to implement complex business logic, integrate with external services, and extend the platform's capabilities.


Creating Functions

Function Structure

typescript
// functions/orders/calculate-total.ts

import { db, context, services, secrets } from '@algorithmshift/runtime';

interface CalculateTotalInput {
  orderId: string;
  couponCode?: string;
}

interface CalculateTotalOutput {
  subtotal: number;
  discount: number;
  tax: number;
  shipping: number;
  total: number;
}

export async function calculateTotal(
  input: CalculateTotalInput
): Promise<CalculateTotalOutput> {
  const { orderId, couponCode } = input;

  // Fetch order with items
  const order = await db.orders.findById(orderId, {
    expand: ['items.product']
  });

  // Calculate subtotal
  let subtotal = 0;
  for (const item of order.items) {
    subtotal += item.quantity * item.product.price;
  }

  // Apply coupon if provided
  let discount = 0;
  if (couponCode) {
    const coupon = await db.coupons.findOne({ code: couponCode });
    if (coupon && coupon.is_active) {
      if (coupon.type === 'percentage') {
        discount = subtotal * (coupon.value / 100);
      } else {
        discount = coupon.value;
      }
    }
  }

  // Calculate tax (8%)
  const taxableAmount = subtotal - discount;
  const tax = taxableAmount * 0.08;

  // Calculate shipping
  const shipping = subtotal >= 100 ? 0 : 9.99;

  // Final total
  const total = taxableAmount + tax + shipping;

  return {
    subtotal,
    discount,
    tax,
    shipping,
    total: Math.round(total * 100) / 100
  };
}

Runtime Context

Available Objects

ObjectDescription
dbDatabase operations
contextRequest context (user, headers)
servicesPre-configured service clients
secretsAccess to workspace secrets
utilsHelper functions
cacheRedis cache operations

Database Operations (db)

typescript
// Find records
const users = await db.users.find({
  where: { is_active: true },
  orderBy: { created_at: 'desc' },
  limit: 10
});

// Find by ID
const user = await db.users.findById('user-uuid');

// Create
const newUser = await db.users.create({
  email: 'new@example.com',
  name: 'New User'
});

// Update
await db.users.update('user-uuid', {
  last_login: new Date()
});

// Transactions
await db.transaction(async (tx) => {
  await tx.orders.create({ ... });
  await tx.inventory.decrement('product-uuid', 'stock', 1);
});

Services (services)

typescript
// Email (SendGrid, SES, etc.)
await services.email.send({
  to: 'user@example.com',
  subject: 'Order Confirmation',
  template: 'order-confirmation',
  data: { orderNumber: 'ORD-123' }
});

// SMS (Twilio)
await services.sms.send({
  to: '+1234567890',
  message: 'Your verification code is 123456'
});

// Storage (S3)
const uploadUrl = await services.storage.getSignedUploadUrl({
  key: 'uploads/image.jpg',
  contentType: 'image/jpeg',
  expiresIn: 3600
});

Error Handling

Built-in Error Types

typescript
import {
  ValidationError,
  NotFoundError,
  UnauthorizedError,
  ForbiddenError,
  ConflictError,
  RateLimitError
} from '@algorithmshift/runtime';

// Validation error (400)
throw new ValidationError('Invalid email format', {
  field: 'email',
  value: input.email
});

// Not found (404)
throw new NotFoundError('Product', productId);

// Forbidden (403)
throw new ForbiddenError('You do not have access to this resource');

Deployment

Deploy Functions

bash
# Deploy all functions
algorithmshift functions deploy

# Deploy specific function
algorithmshift functions deploy orders/calculate-total

# Deploy to specific environment
algorithmshift functions deploy --env staging