@yoryoboy/clickup-sdk
Version:
A modular TypeScript SDK for interacting with the ClickUp API
571 lines (427 loc) ⢠16.8 kB
Markdown
# ClickUp SDK for TypeScript
A modular TypeScript SDK for interacting with the ClickUp API, built with ES modules and object-oriented programming principles.
## š§ Project Overview
This SDK provides a clean, object-oriented interface to the ClickUp API, making it easier to:
- Fetch and manage tasks
- Handle pagination automatically
- Work with ClickUp data in a structured way
## š¦ Installation
```bash
# Clone the repository
git clone https://github.com/yourusername/clickup-sdk.git
# Navigate to the project directory
cd clickup-sdk
# Install dependencies
pnpm install
```
## š Authentication
You'll need a ClickUp API key to use this SDK. You can get one from your ClickUp workspace settings.
Create a `.env` file in the root directory with your API key:
```
CLICKUP_API_KEY=your_api_key_here
```
## š Usage
### Importing the SDK
This package ships dual modules: ESM and CommonJS. Use either style:
- ESM/TypeScript
```ts
import ClickUp, { Task, TaskManager, TeamManager } from '@yoryoboy/clickup-sdk';
```
- CommonJS
```js
const sdk = require('@yoryoboy/clickup-sdk');
const ClickUp = sdk.default; // default export
const { Task, TaskManager, TeamManager } = sdk; // named exports
```
### Basic Example
```typescript
import dotenv from 'dotenv';
import ClickUp from '@yoryoboy/clickup-sdk';
// Load environment variables
dotenv.config();
// Initialize the ClickUp client
const clickUp = new ClickUp(process.env.CLICKUP_API_KEY as string);
// Get tasks from a list
const tasks = await clickUp.tasks.getTasks({
list_id: '123456789',
});
console.log(`Found ${tasks.length} tasks`);
```
### Pagination
The SDK supports automatic pagination when fetching tasks:
```javascript
// Get ALL tasks from a list (handles pagination automatically)
const allTasks = await clickUp.tasks.getTasks({
list_id: '123456789',
page: 'all',
include_closed: true,
});
console.log(`Found ${allTasks.length} tasks across all pages`);
// Get only the first page of tasks
const firstPageTasks = await clickUp.tasks.getTasks({
list_id: '123456789',
page: 0,
});
```
### Filtering Tasks Across a Workspace
Use `getFilteredTasks()` to search for tasks across an entire workspace with powerful filtering options:
```javascript
// Get tasks with specific filters across the workspace
const filteredTasks = await clickUp.tasks.getFilteredTasks({
team_id: '1234567', // Required workspace ID
page: 'all', // Get all pages
statuses: ['in progress', 'review'],
assignees: ['12345'], // User IDs
tags: ['important'],
due_date_gt: Date.now(), // Due date in the future
include_closed: false
});
console.log(`Found ${filteredTasks.length} matching tasks`);
```
### Filtering by Custom Fields
The SDK supports advanced filtering using custom fields:
```javascript
// Filter tasks by custom fields
const tasksWithCustomFields = await clickUp.tasks.getFilteredTasks({
team_id: '1234567',
custom_fields: [
{
field_id: 'abc123def456',
operator: '>',
value: 5
},
{
field_id: 'xyz789',
operator: 'RANGE',
value: [1671246000000, 1671505200000] // Date range
}
]
});
```
### Working with Tasks
Each task is returned as a `Task` instance with helpful methods:
```javascript
const tasks = await clickUp.tasks.getTasks({ list_id: '123456789' });
// Check if a task is completed
const completedTasks = tasks.filter(task => task.isCompleted());
// Get assignee names for a task
const taskWithAssignees = tasks[0];
const assigneeNames = taskWithAssignees.getAssigneeNames();
console.log(`Task assigned to: ${assigneeNames.join(', ')}`);
// Get simplified task data
const simplifiedTask = tasks[0].reduceInfo();
console.log(simplifiedTask);
// Output: { id: '123', name: 'Task Name', status: 'in progress', ... }
```
### Updating Tasks
You can update tasks using the `updateTask` method:
```javascript
// Update a task's status and due date
const updatedTask = await clickUp.tasks.updateTask('task123', {
status: 'in progress',
due_date: Date.now() + 7 * 24 * 60 * 60 * 1000, // One week from now
due_date_time: true
});
console.log(`Task updated: ${updatedTask.name} is now ${updatedTask.status.status}`);
// Update a task's name and description
const renamedTask = await clickUp.tasks.updateTask('task456', {
name: 'New task name',
description: 'Updated description with more details'
});
```
### Simplified Task Data
The `reduceInfo()` method provides a simplified view of task data with a flattened structure:
```javascript
const task = tasks[0];
const info = task.reduceInfo();
```
The simplified object includes:
- Basic task properties (id, name, description, etc.)
- Flattened nested objects (status, creator, etc.)
- Simplified arrays (assignees, watchers as usernames)
- Special handling for dropdown custom fields (shows option names instead of indices)
- Only includes custom fields with defined values
## š API Reference
### ClickUp Class
The main entry point for the SDK.
```javascript
const clickUp = new ClickUp(apiKey);
```
Properties:
- `apiKey`: Your ClickUp API key
- `client`: The configured Axios instance
- `tasks`: TaskManager instance for task operations
### TaskManager Class
Handles all task-related operations.
#### getTasks(params)
Fetches tasks from a ClickUp list.
Parameters:
- `params.list_id` (required): The ClickUp list ID
- `params.page`: Page number or "all" to fetch all pages
- `params.include_closed`: Whether to include closed tasks
- `params.reverse`: Whether to reverse the order of tasks
- ...other ClickUp API parameters
Returns: Promise<Task[]> - Array of Task instances
#### getTask(task_id)
Fetches a single task by its ID and returns its reduced information object.
Parameters:
- `task_id` (required): The ID of the task to retrieve
Returns: Promise<ReducedTask> - Reduced task info
Example:
```javascript
// Get a single task's reduced info
const taskInfo = await clickUp.tasks.getTask('abc123def456');
console.log(taskInfo.id, taskInfo.name, taskInfo.status);
```
#### getFilteredTasks(params)
Fetches filtered tasks across an entire workspace.
Parameters:
- `params.team_id` (required): The ClickUp workspace ID
- `params.page`: Page number or "all" to fetch all pages
- `params.space_ids`: Array of space IDs to filter by
- `params.project_ids`: Array of folder IDs to filter by
- `params.list_ids`: Array of list IDs to filter by
- `params.statuses`: Array of status names to filter by
- `params.assignees`: Array of user IDs to filter by
- `params.tags`: Array of tags to filter by
- `params.due_date_gt/lt`: Filter by due date (Unix timestamp in ms)
- `params.date_created_gt/lt`: Filter by creation date
- `params.date_updated_gt/lt`: Filter by update date
- `params.custom_fields`: Array of custom field filter objects
- ...other ClickUp API parameters
Returns: Promise<Task[]> - Array of Task instances
#### updateTask(task_id, data)
Updates a task with new values.
Parameters:
- `task_id` (required): The ID of the task to update
- `data`: Object containing the fields to update
- `name`: New name for the task
- `description`: New description for the task
- `status`: New status for the task
- `due_date`: New due date (Unix timestamp in ms)
- `due_date_time`: Whether the due date includes a specific time
- `start_date`: New start date (Unix timestamp in ms)
- `time_estimate`: Time estimate in milliseconds
- `archived`: Whether the task is archived
- ...other ClickUp API task fields
Returns: Promise<Task> - The updated Task instance
#### createTask(list_id, taskData)
Creates a new task in a specific list.
Parameters:
- `list_id` (required): The ID of the list to create the task in
- `taskData`: Object containing the task data
- `name` (required): Task name
- `description`: Task description
- `assignees`: Array of assignee user IDs
- `tags`: Array of tags
- `status`: Task status
- `priority`: Task priority (null, 1, 2, 3, or 4)
- `due_date`: Due date (Unix timestamp in ms)
- `start_date`: Start date (Unix timestamp in ms)
- `custom_fields`: Array of custom field objects
- ...other ClickUp API task fields
Returns: Promise<Task> - The created Task instance
#### createTasks(list_id, tasks, options)
Creates multiple tasks with rate limiting to handle ClickUp's API limits.
Parameters:
- `list_id` (required): The ID of the list to create tasks in
- `tasks`: Single task object or array of task objects (see createTask for object structure)
- `options`: Options for batch processing
- `batchSize`: Number of tasks to process per batch (default: 100)
- `delayBetweenBatches`: Delay between batches in milliseconds (default: 60000ms = 1 minute)
- `verbose`: Whether to log progress to console (default: false)
- `onProgress`: Callback function for progress updates
The `onProgress` callback receives a progress object with the following properties:
- For `type: 'batchStart'`:
- `batchNumber`: Current batch number (1-based)
- `totalBatches`: Total number of batches
- `batchSize`: Number of tasks in the current batch
- `tasksProcessed`: Number of tasks processed so far
- `totalTasks`: Total number of tasks to process
- For `type: 'batchComplete'`:
- All of the above, plus:
- `batchDuration`: Time taken to process the batch in milliseconds
- For `type: 'waiting'`:
- `waitTime`: Time to wait before next batch in milliseconds
- `nextBatch`: Next batch number
- `totalBatches`: Total number of batches
- For `type: 'complete'`:
- `totalTasks`: Total number of tasks created
- `totalBatches`: Total number of batches processed
Returns: Promise<Array<Task>> - Array of created Task instances
Example:
```javascript
// Create a single task
const newTask = await clickUp.tasks.createTask("123456789", {
name: "New Task",
description: "Task description",
status: "to do",
due_date: 1735603200000 // Unix timestamp in ms
});
// Create multiple tasks with batching
const tasksToCreate = [
{ name: "Task 1", status: "to do" },
{ name: "Task 2", status: "in progress" },
// ... more tasks
];
const createdTasks = await clickUp.tasks.createTasks("123456789", tasksToCreate, {
batchSize: 50, // Process 50 tasks at a time
delayBetweenBatches: 65000 // Wait 65 seconds between batches
});
```
#### uploadAttachment(task_id, attachment, options)
Uploads a file as an attachment to a task.
Parameters:
- `task_id` (required): The ID of the task to attach the file to.
- `attachment` (required): The attachment source. Can be a local file path (`string`), a `Buffer`, a `Readable` stream, or a `Blob` (Node 18+).
- `options` (optional): An object with optional properties:
- `filename`: A custom name for the attachment.
- `contentType`: The MIME type of the file (e.g., `"image/png"`).
Returns: `Promise<any>` - The attachment creation response from the ClickUp API.
Example:
```javascript
// Upload from a local file path
await clickUp.tasks.uploadAttachment(
"task_123",
"./files/report.pdf",
{ filename: "final-report.pdf" }
);
// Upload from a Buffer in memory
const fileContent = Buffer.from("This is a test file.");
await clickUp.tasks.uploadAttachment(
"task_456",
fileContent,
{ filename: "test.txt", contentType: "text/plain" }
);
```
### ListManager Class
Manages operations related to ClickUp lists.
{{ ... }}
{{ ... }}
Adds a task to an additional list. Note that this requires the "Tasks in Multiple Lists" ClickApp to be enabled in your workspace.
Parameters:
- `list_id` (required): The ID of the list to add the task to
- `task_id` (required): The ID of the task to add to the list
Returns: Promise<Object> - The API response
Example:
```javascript
// Add a task to another list
await clickUp.lists.addTaskToList('123456789', 'abc123def456');
```
#### getList(list_id)
Retrieves a list by its ID.
Parameters:
- `list_id` (required): The ID of the list to retrieve
Returns: Promise<Object> - The list data
Example:
```javascript
// Get list details
const list = await clickUp.lists.getList('123456789');
console.log(list.name);
```
### CustomFieldManager Class
Manages operations related to ClickUp custom fields.
Methods:
- `getListCustomFields(list_id)`: Returns all custom fields for a specific list
- `setCustomFieldValue(params)`: Sets a custom field value for a specific task
#### getListCustomFields(list_id)
Fetches all custom fields available in a specific list.
Parameters:
- `list_id` (required): The ClickUp list ID
Returns: Promise<Array> - Array of custom field objects
Example:
```javascript
// Get custom fields for a list
const customFields = await clickUp.customFields.getListCustomFields('123456789');
console.log(customFields);
```
#### setCustomFieldValue(params)
Sets a custom field value for a specific task.
Parameters:
- `params.task_id` (required): The ID of the task to update
- `params.field_id` (required): The universal unique identifier (UUID) of the custom field
- `params.value` (required): The value to set for the custom field (as a string)
Returns: Promise<Record<string, unknown>> - The API response
Example:
```javascript
// Set a custom field value
const result = await clickUp.customFields.setCustomFieldValue({
task_id: '86b5jqha9',
field_id: 'df45878b-b48e-415d-9561-f8d0392e9f46',
value: 'New Value'
});
```
### TeamManager Class
Manages operations related to ClickUp Teams (workspaces).
#### getTeams()
Fetches all teams the API key has access to using `GET /team`.
Parameters:
- None
Returns: `Promise<Teams>` ā where `Teams` is `{ teams: Team[] }` as defined in `src/types/index.ts`.
Example:
```javascript
// Retrieve teams (workspaces)
const { teams } = await clickUp.teams.getTeams();
// List team names
console.log(teams.map(t => t.name));
// Safely access members (may be empty or undefined depending on permissions)
for (const team of teams) {
console.log(`Team: ${team.name} (members: ${team.members?.length ?? 0})`);
}
```
### Task Class
Wrapper for individual task objects with helpful methods.
#### Instance Methods
- `getAssigneeNames()`: Returns an array of assignee usernames
- `isCompleted()`: Returns true if the task status is "done"
- `reduceInfo()`: Returns a simplified object with flattened task data
- Converts nested properties into flat key-value pairs
- Transforms dropdown custom fields to show option names instead of indices
- Filters out custom fields with undefined values
#### Static Methods
- `Task.reduceInfo(tasks)`: Utility method that handles both single tasks and arrays of tasks
- If given a single Task instance, returns its reduced info object
- If given an array of Task instances, returns an array of reduced info objects
- Eliminates the need for `tasks.map(task => task.reduceInfo())`
Example:
```javascript
// For a single task
const reducedTask = Task.reduceInfo(task);
// For an array of tasks - no need for .map() anymore!
const reducedTasks = Task.reduceInfo(tasks);
```
## š§± Project Structure
```
clickup-sdk/
āāā src/
ā āāā api/
ā ā āāā axiosClient.ts # Axios client configuration
ā āāā core/
ā ā āāā ClickUp.ts # Main SDK class
ā ā āāā TaskManager.ts # Task operations
ā ā āāā ListManager.ts # List operations
ā ā āāā CustomFieldManager.ts # Custom fields operations
ā ā āāā Task.ts # Task wrapper class
ā āāā utils/
ā ā āāā queryBuilder.ts # Query string builder
ā āāā index.ts # Package entry point
āāā examples/
ā āāā basic-usage.ts # Example usage
āāā .env # Environment variables
āāā .gitignore
āāā package.json
āāā README.md
```
## š ļø Development
### Adding New Features
To add new features or API endpoints:
1. Create a new manager class in the `src/core` directory
2. Add the manager to the ClickUp class
3. Implement the API methods in the manager class
### Testing
You can test the SDK by modifying the `index.ts` file and running:
```bash
node index.ts
```
## š License
This project is licensed under the MIT License - see the LICENSE file for details.