@renderinc/sdk
v0.1.0
Published
Render SDK for TypeScript
Readme
Render Workflow SDK for TypeScript
The official TypeScript SDK for Render Workflows, providing a simple and intuitive API for managing and executing tasks.
Features
- REST API Client: Run, monitor, and manage task runs
- Task Definition SDK: Define and register tasks with decorators
- Server-Sent Events: Real-time streaming of task run events
- Async/Await Support: Modern Promise-based API
- TypeScript First: Full type safety and IntelliSense support
- Retry Logic: Configurable retry behavior for tasks
- Subtask Execution: Execute tasks from within other tasks
Installation
npm install @renderinc/sdkOr with yarn:
yarn add @renderinc/sdkOr with pnpm:
pnpm add @renderinc/sdkQuick Start
REST API Client
Use the Render SDK to run tasks and monitor their execution:
import { Render } from '@renderinc/sdk';
// Create a Render SDK instance (uses RENDER_API_KEY from environment)
const render = new Render();
// Run a task and wait for completion
const result = await render.workflows.runTask('my-workflow/my-task', [42, 'hello']);
console.log('Status:', result.status);
console.log('Results:', result.results);
// List recent task runs
const taskRuns = await render.workflows.listTaskRuns({ limit: 10 });
// Get specific task run
const details = await render.workflows.getTaskRun(result.id);Alternatively, you can create a workflows client directly:
import { createWorkflowsClient } from '@renderinc/sdk/workflows';
const client = createWorkflowsClient();
const result = await client.runTask('my-workflow/my-task', [42, 'hello']);Task Definition
Define tasks that can be executed by the workflow system:
import { task, startTaskServer } from '@renderinc/sdk/workflows';
// Simple task
const square = task(
{ name: 'square' },
function square(a: number): number {
return a * a;
}
);
// Async task with subtask execution
task(
{ name: 'addSquares' },
async function addSquares(a: number, b: number): Promise<number> {
const result1 = await square(a);
const result2 = await square(b);
return result1 + result2;
}
);
// Task with custom options
task(
{
name: 'retryableTask',
retry: {
maxRetries: 3,
waitDurationMs: 1000,
factor: 1.5,
},
},
async function retryableTask(input: string): Promise<string> {
// Task implementation
return input.toUpperCase();
}
);
// Start the task server
await startTaskServer();API Reference
Render SDK
new Render(options?)
Creates a new Render SDK instance with access to all Render products.
Options:
token?: string- API token (defaults toRENDER_API_KEYenv var)baseUrl?: string- Base URL (defaults tohttps://api.render.com)useLocalDev?: boolean- Use local development modelocalDevUrl?: string- Local development URL
Properties:
workflows- WorkflowsClient instance for managing workflow tasks
Example:
import { Render } from '@renderinc/sdk';
const render = new Render({
token: 'your-api-token',
baseUrl: 'https://api.render.com',
});
// Access workflows client
const result = await render.workflows.runTask('my-workflow/task', [42]);Workflows Client API
The workflows client is accessible via render.workflows or can be created directly using createWorkflowsClient:
import { createWorkflowsClient } from '@renderinc/sdk/workflows';
const client = createWorkflowsClient({
token: 'your-api-token',
baseUrl: 'https://api.render.com',
});Workflows Client Methods
render.workflows.runTask(taskIdentifier, inputData, signal?)
Runs a task and waits for completion.
Parameters:
taskIdentifier: string- Task identifier in format "workflow-slug/task-name"inputData: any[]- Input data as array of parameterssignal?: AbortSignal- Optional abort signal for cancellation
Returns: Promise<TaskRunDetails>
Example:
const render = new Render();
const result = await render.workflows.runTask('my-workflow/square', [5]);
console.log('Results:', result.results);render.workflows.getTaskRun(taskRunId)
Gets task run details by ID.
Parameters:
taskRunId: string- Task run ID
Returns: Promise<TaskRunDetails>
Example:
const render = new Render();
const details = await render.workflows.getTaskRun('task-run-id');render.workflows.listTaskRuns(params)
Lists task runs with optional filters.
Parameters:
params.limit?: number- Maximum number of resultsparams.cursor?: string- Pagination cursorparams.ownerId?: string[]- Filter by owner IDs
Returns: Promise<TaskRun[]>
Example:
const render = new Render();
const taskRuns = await render.workflows.listTaskRuns({ limit: 10 });Task API
task(options, func)
Registers a function as a task.
Parameters:
options: RegisterTaskOptions- Task configurationname: string- Task name (required)retry?: RetryOptions- Optional retry configurationmaxRetries: number- Maximum number of retrieswaitDurationMs: number- Wait duration between retries in millisecondsfactor?: number- Backoff factor (default: 1.5)
func: TaskFunction- The task function to register
Returns: The registered function with the same signature
Usage:
// Basic usage
const myTask = task(
{ name: 'myTask' },
function myTask(arg: string): string {
return arg.toUpperCase();
}
);
// With retry options
task(
{
name: 'retryableTask',
retry: {
maxRetries: 3,
waitDurationMs: 1000,
factor: 1.5,
},
},
function retryableTask(arg: string): string {
return arg.toUpperCase();
}
);
// Async task with subtasks
const square = task(
{ name: 'square' },
function square(a: number): number {
return a * a;
}
);
task(
{ name: 'addSquares' },
async function addSquares(a: number, b: number): Promise<number> {
const result1 = await square(a);
const result2 = await square(b);
return result1 + result2;
}
);startTaskServer()
Starts the task server and listens for task execution requests.
Returns: Promise<void>
Example:
await startTaskServer();Types
TaskRunStatus
enum TaskRunStatus {
PENDING = 'pending',
RUNNING = 'running',
COMPLETED = 'completed',
FAILED = 'failed',
}TaskRun
interface TaskRun {
id: string;
status: TaskRunStatus;
created_at: string;
updated_at: string;
task_identifier: string;
}TaskRunDetails
interface TaskRunDetails extends TaskRun {
completed_at?: string;
results?: any[];
error?: string;
}RegisterTaskOptions
interface RegisterTaskOptions {
name: string;
retry?: {
maxRetries: number;
waitDurationMs: number;
factor?: number; // default 1.5
};
}Error Handling
The SDK provides several error classes:
import { Render } from '@renderinc/sdk';
import {
RenderError,
ClientError,
ServerError,
AbortError,
} from '@renderinc/sdk';
const render = new Render();
try {
const result = await render.workflows.runTask('my-workflow/task', [42]);
} catch (error) {
if (error instanceof ClientError) {
console.error('Client error:', error.statusCode, error.cause);
} else if (error instanceof ServerError) {
console.error('Server error:', error.statusCode, error.cause);
} else if (error instanceof AbortError) {
console.error('Request was aborted');
} else if (error instanceof RenderError) {
console.error('General SDK error:', error.message);
}
}Environment Variables
RENDER_API_KEY- Your Render API key (required)RENDER_USE_LOCAL_DEV- Enable local development mode (true/false)RENDER_LOCAL_DEV_URL- Local development URL (default:http://localhost:8120)RENDER_SDK_MODE- Task execution mode (runorregister)RENDER_SDK_SOCKET_PATH- Unix socket path for task communication
Examples
Example 1: Running a Task
import { Render } from '@renderinc/sdk';
const render = new Render();
async function runSquareTask() {
const result = await render.workflows.runTask('my-workflow/square', [5]);
console.log('Square of 5 is:', result.results[0]); // 25
}
runSquareTask();Example 2: Defining Tasks with Subtasks
import { task, startTaskServer } from '@renderinc/sdk/workflows';
const square = task(
{ name: 'square' },
function square(a: number): number {
return a * a;
}
);
task(
{ name: 'pythagorean' },
async function pythagorean(a: number, b: number): Promise<number> {
const aSquared = await square(a);
const bSquared = await square(b);
return Math.sqrt(aSquared + bSquared);
}
);
await startTaskServer();Example 3: Error Handling in Tasks
import { task } from '@renderinc/sdk/workflows';
const divide = task(
{ name: 'divide' },
async function divide(a: number, b: number): Promise<number> {
if (b === 0) {
throw new Error('Cannot divide by zero');
}
return a / b;
}
);
task(
{
name: 'safeDivide',
retry: {
maxRetries: 3,
waitDurationMs: 1000,
},
},
async function safeDivide(a: number, b: number): Promise<number> {
try {
return await divide(a, b);
} catch (error) {
console.error('Division failed:', error);
return 0; // Return default value
}
}
);Example 4: Using AbortSignal for Cancellation
import { Render, AbortError } from '@renderinc/sdk';
const render = new Render();
async function runTaskWithCancellation() {
const abortController = new AbortController();
// Cancel the task after 5 seconds
setTimeout(() => abortController.abort(), 5000);
try {
const result = await render.workflows.runTask(
'my-workflow/long-running-task',
[42],
abortController.signal
);
console.log('Task completed:', result.results);
} catch (error) {
if (error instanceof AbortError) {
console.log('Task was cancelled');
} else {
console.error('Task failed:', error);
}
}
}
runTaskWithCancellation();Example 5: Using the Unified Render SDK
import { Render } from '@renderinc/sdk';
// Single entry point for all Render products
const render = new Render({
token: process.env.RENDER_API_KEY,
});
async function workflowExample() {
try {
// Run a workflow task
const result = await render.workflows.runTask('my-workflow/process-data', [
{ userId: 123, data: 'example' },
]);
console.log('Workflow completed:', result.status);
console.log('Results:', result.results);
// List and monitor recent task runs
const recentRuns = await render.workflows.listTaskRuns({ limit: 5 });
console.log(`\nRecent task runs: ${recentRuns.length}`);
for (const run of recentRuns) {
const details = await render.workflows.getTaskRun(run.id);
console.log(`- ${run.taskId}: ${details.status}`);
}
} catch (error) {
console.error('Error:', error);
}
}
workflowExample();Development
Building
npm run buildTesting
npm testLinting
npm run lintFormatting
npm run formatProject Structure
typescript/
├── src/
│ ├── render.ts # Main Render SDK class
│ ├── index.ts # Main exports
│ └── workflows/ # Workflows functionality
│ ├── client/ # REST API client
│ │ ├── client.ts # WorkflowsClient class
│ │ ├── workflows.ts # WorkflowsService
│ │ ├── sse.ts # SSE client
│ │ ├── types.ts # Type definitions
│ │ ├── errors.ts # Error classes
│ │ └── index.ts # Exports
│ ├── task/ # Task execution SDK
│ │ ├── task.ts # task() function
│ │ ├── runner.ts # start() and run()
│ │ ├── executor.ts # TaskExecutor
│ │ ├── registry.ts # TaskRegistry
│ │ ├── uds.ts # Unix socket client
│ │ ├── types.ts # Type definitions
│ │ └── index.ts # Exports
│ └── index.ts # Workflows exports
├── examples/
│ ├── client/ # Client example
│ │ ├── main.ts
│ │ └── package.json
│ └── task/ # Task example
│ ├── main.ts
│ └── package.json
├── package.json
├── tsconfig.json
└── README.mdLicense
MIT
Support
For issues and questions, please visit:
- GitHub Issues: https://github.com/renderinc/workflow-sdk/issues
- Documentation: https://render.com/docs/workflows
Contributing
Contributions are welcome! Please read our contributing guidelines before submitting pull requests.
