UNPKG

@yoryoboy/clickup-sdk

Version:

A modular TypeScript SDK for interacting with the ClickUp API

571 lines (427 loc) • 16.8 kB
# 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.