npm package: @fold-run/sdk
Description: TypeScript SDK for the fold.run API
Latest version: 0.2.0

# @fold-run/sdk

TypeScript SDK for the [fold.run](https://fold.run) API. Manage tenants, deploy functions, query activations, and stream real-time events.

## Install

```bash
npm install @fold-run/sdk
```

## Quick Start

```ts
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

```ts
// 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:

```ts
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:

```ts
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:

```ts
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:

```ts
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

```ts
client.listTenants({ page?, limit? })
client.createTenant({ name, plan? })
client.getTenant(id)
client.generateTenantToken(tenantId, { role? })
```

### Functions

```ts
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

```ts
client.listBindings(functionId)
client.addBinding(functionId, bindingId)
client.removeBinding(functionId, bindingId)
```

### Permissions

```ts
client.listFunctionPermissions(functionId)
client.addFunctionPermission(functionId, { user_id, permission? })
client.removeFunctionPermission(functionId, userId, permission?)
```

### Activations

```ts
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

```ts
client.updateErrorGroup(id, { status: 'open' | 'resolved' }, tenantId?)
client.resolveErrorGroup(id, tenantId?)
```

### Invocation

```ts
const res = await client.invoke('my-tenant', 'my-function', {
  method: 'POST',
  body: { message: 'hello' },
});
const data = await res.json();
```

### Schedules

```ts
client.listSchedules()
client.createSchedule({ function_id, cron_expression })
client.updateSchedule(functionId, { enabled?, cron_expression? })
client.deleteSchedule(functionId)
```

### Usage

```ts
client.getUsage(tenantId, days?) // default: 30 days
```

### API Keys

```ts
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

```ts
client.listHooks(tenantId)
client.createHook(tenantId, { event, url, secret? })
client.deleteHook(id)
```

### Logs

```ts
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

```ts
client.listSecrets(tenantId)
client.setSecret(tenantId, name, value)
client.deleteSecret(tenantId, name)
```

### Teams

```ts
client.listTeamMembers(tenantId)
client.inviteTeamMember(tenantId, { email, role? })
client.removeTeamMember(tenantId, userId)
client.acceptTeamInvite({ token, password? })       // no auth required
```

### Custom Domains

```ts
client.listDomains(tenantId)
client.addDomain(tenantId, hostname)
client.deleteDomain(tenantId, hostname)
```

## TypeScript

Ships with full TypeScript declarations:

```ts
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