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
| Object | Description |
|---|---|
db | Database operations |
context | Request context (user, headers) |
services | Pre-configured service clients |
secrets | Access to workspace secrets |
utils | Helper functions |
cache | Redis 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