HTTP client
The$http namespace provides methods for making HTTP requests.
Basic request
const response = $http.send({
url: "https://api.example.com/data",
method: "GET",
timeout: 30, // seconds
})
console.log("Status:", response.statusCode)
console.log("Body:", toString(response.body))
console.log("JSON:", response.json)
POST request with JSON
const response = $http.send({
url: "https://api.example.com/users",
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": "Bearer TOKEN",
},
body: JSON.stringify({
name: "John Doe",
email: "john@example.com",
}),
timeout: 30,
})
if (response.statusCode === 201) {
console.log("User created:", response.json)
} else {
console.log("Error:", response.statusCode)
}
POST with FormData
const formData = new FormData()
formData.append("name", "John Doe")
formData.append("email", "john@example.com")
const response = $http.send({
url: "https://api.example.com/upload",
method: "POST",
body: formData,
timeout: 60,
})
console.log("Response:", response.json)
Handle response
const response = $http.send({
url: "https://api.example.com/data",
method: "GET",
})
// Response object properties
console.log("Status code:", response.statusCode)
console.log("Headers:", response.headers)
console.log("Cookies:", response.cookies)
console.log("Body (bytes):", response.body)
console.log("Body (string):", toString(response.body))
console.log("JSON:", response.json) // Auto-parsed if JSON
Security utilities
The$security namespace provides cryptographic and security functions.
Hashing
// MD5
const md5Hash = $security.md5("hello world")
console.log("MD5:", md5Hash)
// SHA256
const sha256Hash = $security.sha256("hello world")
console.log("SHA256:", sha256Hash)
// SHA512
const sha512Hash = $security.sha512("hello world")
console.log("SHA512:", sha512Hash)
// HMAC SHA256
const hmac256 = $security.hs256("hello world", "secret-key")
console.log("HMAC-SHA256:", hmac256)
// HMAC SHA512
const hmac512 = $security.hs512("hello world", "secret-key")
console.log("HMAC-SHA512:", hmac512)
Secure comparison
// Constant-time comparison (prevents timing attacks)
const hash1 = $security.sha256("password123")
const hash2 = $security.sha256("password123")
const isEqual = $security.equal(hash1, hash2)
console.log("Hashes match:", isEqual)
Random strings
// Cryptographically secure random string (default 32 chars)
const token = $security.randomString(32)
console.log("Token:", token)
// Custom alphabet
const customToken = $security.randomStringWithAlphabet(16, "0123456789ABCDEF")
console.log("Hex token:", customToken)
// Regex pattern
const pinCode = $security.randomStringByRegex("[0-9]{6}")
console.log("PIN:", pinCode)
// Pseudo-random (faster, less secure)
const pseudo = $security.pseudorandomString(32)
console.log("Pseudo:", pseudo)
const pseudoCustom = $security.pseudorandomStringWithAlphabet(16, "ABCDEFGH12345678")
console.log("Pseudo custom:", pseudoCustom)
Encryption
// Encrypt data
const key = "my-secret-key-32-chars-long!!!"
const plaintext = "sensitive data"
const encrypted = $security.encrypt(plaintext, key)
console.log("Encrypted:", encrypted)
// Decrypt data
const decrypted = $security.decrypt(encrypted, key)
console.log("Decrypted:", decrypted)
JWT tokens
// Create JWT
const payload = {
userId: "user123",
role: "admin",
exp: Math.floor(Date.now() / 1000) + (60 * 60), // 1 hour
}
const token = $security.createJWT(
payload,
"my-secret-key",
3600 // 1 hour in seconds
)
console.log("JWT:", token)
// Parse JWT (without verification)
const unverified = $security.parseUnverifiedJWT(token)
console.log("Payload:", unverified)
// Parse and verify JWT
try {
const verified = $security.parseJWT(token, "my-secret-key")
console.log("Verified payload:", verified)
} catch (err) {
console.log("Invalid token:", err.message)
}
Cron jobs
Schedule recurring tasks with cron expressions.Basic cron job
// Runs every hour
cronAdd("cleanup", "0 * * * *", () => {
console.log("Running cleanup task")
// Delete old logs
const cutoff = new DateTime()
cutoff.addDate(0, 0, -30) // 30 days ago
const logs = arrayOf(new Record())
$app.recordQuery("logs")
.andWhere($dbx.exp("created < {:cutoff}", {cutoff: cutoff.string()}))
.all(logs)
for (let log of logs) {
$app.delete(log)
}
console.log("Deleted", logs.length, "old logs")
})
Cron expressions
// Every 5 minutes
cronAdd("task1", "*/5 * * * *", () => {
console.log("Every 5 minutes")
})
// Every day at midnight
cronAdd("task2", "0 0 * * *", () => {
console.log("Daily task")
})
// Every Monday at 9 AM
cronAdd("task3", "0 9 * * 1", () => {
console.log("Monday morning task")
})
// Every 1st day of month at 3 AM
cronAdd("task4", "0 3 1 * *", () => {
console.log("Monthly task")
})
Remove cron job
// Remove a cron job
cronRemove("cleanup")
Date and time
DateTime object
// Current date/time
const now = new DateTime()
console.log("Now:", now.string())
// Parse from string
const date = new DateTime("2024-01-15 10:30:00.000Z")
console.log("Parsed:", date.string())
// With timezone
const date2 = new DateTime("2024-01-15 10:30:00", "America/New_York")
console.log("With timezone:", date2.string())
Date manipulation
const date = new DateTime()
// Add time
date.addDate(1, 2, 3) // Add 1 year, 2 months, 3 days
date.addTime(4, 5, 6, 0) // Add 4 hours, 5 minutes, 6 seconds
console.log("Modified:", date.string())
Timezone
// Create timezone
const tz = new Timezone("America/Los_Angeles")
// Use with DateTime
const date = new DateTime("2024-01-15 10:00:00", "America/Los_Angeles")
console.log("LA time:", date.string())
Type conversion
toString
// Convert various types to string
const str1 = toString(123) // "123"
const str2 = toString(true) // "true"
const str3 = toString([1, 2, 3]) // "[1,2,3]"
const str4 = toString({key: "value"}) // '{"key":"value"}'
// Convert reader to string
const body = toString(e.request.body, 1048576) // Max 1MB
toBytes
// Convert to byte array
const bytes1 = toBytes("hello") // [104, 101, 108, 108, 111]
const bytes2 = toBytes(123) // [49, 50, 51]
const bytes3 = toBytes({key: "value"}) // JSON bytes
// Convert reader to bytes
const bodyBytes = toBytes(e.request.body, 1048576) // Max 1MB
unmarshal
// Merge data into object
const record = new Record()
unmarshal({title: "Hello", content: "World"}, record)
console.log(record.getString("title")) // "Hello"
console.log(record.getString("content")) // "World"
Arrays
arrayOf
// Create typed array for database results
const records = arrayOf(new Record())
$app.recordQuery("posts").limit(10).all(records)
console.log("Found", records.length, "posts")
// For collections
const collections = arrayOf(new Collection())
$app.findAllCollections(collections)
Sleep
// Pause execution
console.log("Starting...")
sleep(2000) // Sleep for 2 seconds (2000ms)
console.log("Done!")
Context
Create Go context objects for API calls:// Create blank context
const ctx = new Context()
// Create with value
const ctx2 = new Context(null, "requestId", "12345")
console.log(ctx2.value("requestId")) // "12345"
// Chain contexts
const ctx3 = new Context(ctx2, "userId", "user123")
console.log(ctx3.value("requestId")) // "12345"
console.log(ctx3.value("userId")) // "user123"
Validation
ValidationError
// Create validation error
const error = new ValidationError("validation_required", "This field is required")
// Throw in hook
onRecordValidate((e) => {
if (e.collection.name === "posts") {
const title = e.record.getString("title")
if (!title || title.length < 3) {
throw new ValidationError(
"validation_min_length",
"Title must be at least 3 characters"
)
}
}
return e.next()
}, "posts")
API errors
Create proper HTTP error responses:// Bad Request (400)
throw new BadRequestError("Invalid input")
// Unauthorized (401)
throw new UnauthorizedError("Authentication required")
// Forbidden (403)
throw new ForbiddenError("Access denied")
// Not Found (404)
throw new NotFoundError("Resource not found")
// Too Many Requests (429)
throw new TooManyRequestsError("Rate limit exceeded")
// Internal Server Error (500)
throw new InternalServerError("Something went wrong")
// Custom API error
throw new ApiError(418, "I'm a teapot", null)
Environment variables
// Get environment variable
const apiKey = $os.getenv("API_KEY")
const environment = $os.getenv("ENVIRONMENT") || "production"
console.log("API Key:", apiKey)
console.log("Environment:", environment)
Examples
Webhook integration
onRecordAfterCreateSuccess((e) => {
if (e.collection.name === "orders") {
const record = e.record
// Send webhook notification
try {
const response = $http.send({
url: "https://webhook.example.com/orders",
method: "POST",
headers: {
"Content-Type": "application/json",
"X-Webhook-Secret": $os.getenv("WEBHOOK_SECRET"),
},
body: JSON.stringify({
event: "order.created",
order_id: record.id,
total: record.getFloat("total"),
customer: record.getString("customer"),
}),
timeout: 10,
})
console.log("Webhook sent:", response.statusCode)
} catch (err) {
console.log("Webhook failed:", err.message)
}
}
return e.next()
}, "orders")
Rate limiting
const rateLimits = {}
routerAdd("POST", "/api/expensive-operation", (e) => {
const clientIP = e.realIP()
const now = Date.now()
const limit = 10 // Max 10 requests
const window = 60000 // Per 60 seconds
// Initialize or clean up old entries
if (!rateLimits[clientIP]) {
rateLimits[clientIP] = []
}
// Remove expired timestamps
rateLimits[clientIP] = rateLimits[clientIP].filter(
timestamp => now - timestamp < window
)
// Check limit
if (rateLimits[clientIP].length >= limit) {
throw new TooManyRequestsError("Rate limit exceeded. Try again later.")
}
// Add current request
rateLimits[clientIP].push(now)
// Process request
return e.json(200, {success: true})
}, $apis.requireAuth())
API key authentication
const apiKeyMiddleware = new Middleware((e) => {
const apiKey = e.request.header.get("X-API-Key")
if (!apiKey) {
throw new UnauthorizedError("API key required")
}
// Verify API key
const validKey = $os.getenv("API_KEY")
const isValid = $security.equal(apiKey, validKey)
if (!isValid) {
throw new UnauthorizedError("Invalid API key")
}
return e.next()
}, 0, "api_key_auth")
routerAdd("GET", "/api/protected", (e) => {
return e.json(200, {message: "Access granted"})
}, apiKeyMiddleware)