@fold-run/sdk
v0.2.0
Published
TypeScript SDK for the fold.run API
Readme
@fold-run/sdk
TypeScript SDK for the fold.run API. Manage tenants, deploy functions, query activations, and stream real-time events.
Install
npm install @fold-run/sdkQuick Start
import { FoldClient } from '@fold-run/sdk';
const client = new FoldClient({ apiKey: 'fold_...' });
// Deploy a function
const { id, version } = await client.deploy('my-tenant', {
name: 'hello',
code: `export default { async fetch(req) { return new Response("Hello!") } }`,
});
// List functions
const { functions } = await client.listFunctions({ tenant_id: 'my-tenant' });
// Invoke a deployed function
const response = await client.invoke('my-tenant', 'hello');
console.log(await response.text()); // "Hello!"Authentication
// API key (recommended for production)
const client = new FoldClient({ apiKey: 'fold_...' });
// Session token (from login flow)
const client = new FoldClient({ token: 'eyJ...' });
// Custom base URL for local development
const client = new FoldClient({ apiKey: 'fold_...', baseUrl: 'http://localhost:8787' });Timeout & Retry
Requests time out after 30 seconds by default. Configure retries with exponential backoff for transient failures:
const client = new FoldClient({
apiKey: 'fold_...',
timeout: 10_000, // 10s timeout
retry: {
maxRetries: 3, // retry up to 3 times (default: 0)
baseDelay: 500, // 500ms base delay with exponential backoff
retryableStatuses: [429, 500, 502, 503, 504], // default
},
});Error Handling
All API errors throw FoldApiError with structured fields. Use ErrorCodes constants for type-safe matching:
import { FoldClient, FoldApiError, ErrorCodes } from '@fold-run/sdk';
try {
await client.getFunction('missing');
} catch (err) {
if (err instanceof FoldApiError) {
console.log(err.status); // 404
console.log(err.code); // "FUNCTION_NOT_FOUND"
console.log(err.message); // "Function not found"
if (err.hasCode(ErrorCodes.FUNCTION_NOT_FOUND)) {
// handle missing function
}
if (err.hasCode(ErrorCodes.RATE_LIMITED)) {
// back off and retry
}
}
}Pagination
List methods return { page, has_more } for manual pagination. Use the built-in paginate helper to auto-iterate all pages:
for await (const fn of client.paginate(p => client.listFunctions(p), 'functions')) {
console.log(fn.name);
}
// With custom page size
for await (const a of client.paginate(p => client.listActivations(p), 'activations', { limit: 100 })) {
console.log(a.id);
}Streaming
Stream real-time logs and activations via SSE:
for await (const log of client.streamLogs('my-tenant', { level: 'error' })) {
console.log(log.message);
}
for await (const activation of client.streamActivations({ tenant_id: 'my-tenant' })) {
console.log(activation.status, activation.duration_ms);
}API Reference
Tenants
client.listTenants({ page?, limit? })
client.createTenant({ name, plan? })
client.getTenant(id)
client.generateTenantToken(tenantId, { role? })Functions
client.listFunctions({ tenant_id?, status?, page?, limit? })
client.getFunction(id)
client.deploy(tenantId, { name, code, language? })
client.deleteFunction(id)
client.rollback(functionId, version)
client.getFunctionMetrics({ days? })
client.getFunctionReview(functionId)Bindings
client.listBindings(functionId)
client.addBinding(functionId, bindingId)
client.removeBinding(functionId, bindingId)Permissions
client.listFunctionPermissions(functionId)
client.addFunctionPermission(functionId, { user_id, permission? })
client.removeFunctionPermission(functionId, userId, permission?)Activations
client.listActivations({ tenant_id?, function_id?, status?, page?, limit? })
client.getActivation(id, tenantId?)
client.replayActivation(id, tenantId?)
client.bulkReplay(activationIds, tenantId?)
client.getErrorGroups({ tenant_id?, since?, limit? })Error Groups
client.updateErrorGroup(id, { status: 'open' | 'resolved' }, tenantId?)
client.resolveErrorGroup(id, tenantId?)Invocation
const res = await client.invoke('my-tenant', 'my-function', {
method: 'POST',
body: { message: 'hello' },
});
const data = await res.json();Schedules
client.listSchedules()
client.createSchedule({ function_id, cron_expression })
client.updateSchedule(functionId, { enabled?, cron_expression? })
client.deleteSchedule(functionId)Usage
client.getUsage(tenantId, days?) // default: 30 daysAPI Keys
client.listApiKeys(tenantId)
client.createApiKey(tenantId, { name, scopes? }) // returns full key once
client.updateApiKey(id, { name })
client.rotateApiKey(id) // returns new key once
client.deleteApiKey(id)Webhooks
client.listHooks(tenantId)
client.createHook(tenantId, { event, url, secret? })
client.deleteHook(id)Logs
client.getLogs(tenantId, { function_id?, level?, q?, since?, limit? })
client.searchArchivedLogs(tenantId, { q?, since?, limit? })
client.searchLogs(tenantId, { function_id?, level?, q?, since?, until?, limit? }) // unified
client.streamLogs(tenantId, { function_id?, level? })Secrets
client.listSecrets(tenantId)
client.setSecret(tenantId, name, value)
client.deleteSecret(tenantId, name)Teams
client.listTeamMembers(tenantId)
client.inviteTeamMember(tenantId, { email, role? })
client.removeTeamMember(tenantId, userId)
client.acceptTeamInvite({ token, password? }) // no auth requiredCustom Domains
client.listDomains(tenantId)
client.addDomain(tenantId, hostname)
client.deleteDomain(tenantId, hostname)TypeScript
Ships with full TypeScript declarations:
import type {
FoldFunction,
FoldActivation,
FoldTenant,
FoldSecret,
FoldSchedule,
FoldApiKey,
FoldHook,
FoldDomain,
FoldTeamMember,
FoldUsage,
FoldErrorGroup,
FoldBinding,
FoldFunctionMetrics,
FoldFunctionPermission,
FoldResolvedErrorGroup,
DeployOptions,
FoldClientOptions,
} from '@fold-run/sdk';
import { ErrorCodes } from '@fold-run/sdk';
import type { ErrorCode } from '@fold-run/sdk';License
MIT
