Skip to main content
Glama
attachments-enhanced.ts10.4 kB
import { ClickUpClient } from './index.js'; import type { UploadAttachmentRequest, UpdateAttachmentMetadataRequest, GetAttachmentsFilter, AttachmentSharingRequest, BulkAttachmentOperation, AttachmentResponse, AttachmentListResponse, AttachmentUploadResponse, AttachmentStatsResponse } from '../schemas/attachments-schemas.js'; export class AttachmentsEnhancedClient extends ClickUpClient { constructor(apiToken: string) { super({ apiToken }); } /** * Upload a new attachment */ async uploadAttachment(request: UploadAttachmentRequest): Promise<AttachmentUploadResponse> { const endpoint = this.getParentEndpoint(request.parent_type, request.parent_id); const payload: any = { filename: request.filename, source: request.source, description: request.description, tags: request.tags }; if (request.file_data) { payload.file_data = request.file_data; } else if (request.file_url) { payload.file_url = request.file_url; } const response = await this.post<AttachmentUploadResponse>(`${endpoint}/attachment`, payload); return response; } /** * Get attachments for a parent object */ async getAttachments(filter: GetAttachmentsFilter): Promise<AttachmentListResponse> { const endpoint = this.getParentEndpoint(filter.parent_type, filter.parent_id); const params = new URLSearchParams(); if (filter.type) params.append('type', filter.type); if (filter.filename_contains) params.append('filename_contains', filter.filename_contains); if (filter.tags) params.append('tags', filter.tags.join(',')); if (filter.date_from) params.append('date_from', filter.date_from.toString()); if (filter.date_to) params.append('date_to', filter.date_to.toString()); if (filter.limit) params.append('limit', filter.limit.toString()); if (filter.offset) params.append('offset', filter.offset.toString()); const queryString = params.toString(); const fullEndpoint = `${endpoint}/attachment${queryString ? `?${queryString}` : ''}`; const response = await this.get<AttachmentListResponse>(fullEndpoint); return response; } /** * Get a specific attachment by ID */ async getAttachment(attachmentId: string): Promise<AttachmentResponse> { const response = await this.get<{ attachment: AttachmentResponse }>(`/attachment/${attachmentId}`); return response.attachment; } /** * Update attachment metadata */ async updateAttachmentMetadata(request: UpdateAttachmentMetadataRequest): Promise<AttachmentResponse> { const updateData: Record<string, any> = {}; if (request.filename) updateData.filename = request.filename; if (request.description !== undefined) updateData.description = request.description; if (request.tags) updateData.tags = request.tags; const response = await this.put<{ attachment: AttachmentResponse }>( `/attachment/${request.attachment_id}`, updateData ); return response.attachment; } /** * Delete an attachment */ async deleteAttachment(attachmentId: string): Promise<{ success: boolean }> { await this.delete(`/attachment/${attachmentId}`); return { success: true }; } /** * Download an attachment */ async downloadAttachment(attachmentId: string): Promise<{ filename: string; mimetype: string; size: number; download_url: string; expires_at: string; }> { const response = await this.get<{ filename: string; mimetype: string; size: number; download_url: string; expires_at: string; }>(`/attachment/${attachmentId}/download`); return response; } /** * Get attachment info without downloading */ async getAttachmentInfo(attachmentId: string): Promise<{ attachment: AttachmentResponse; download_info: { can_download: boolean; download_url?: string; expires_at?: string; requires_auth: boolean; }; preview_info: { can_preview: boolean; preview_url?: string; thumbnail_url?: string; preview_type?: string; }; }> { const response = await this.get<{ attachment: AttachmentResponse; download_info: { can_download: boolean; download_url?: string; expires_at?: string; requires_auth: boolean; }; preview_info: { can_preview: boolean; preview_url?: string; thumbnail_url?: string; preview_type?: string; }; }>(`/attachment/${attachmentId}/info`); return response; } /** * Update attachment sharing settings */ async updateAttachmentSharing(request: AttachmentSharingRequest): Promise<AttachmentResponse> { const payload = { access_level: request.access_level, expires_at: request.expires_at ? new Date(request.expires_at * 1000).toISOString() : undefined, password: request.password }; const response = await this.put<{ attachment: AttachmentResponse }>( `/attachment/${request.attachment_id}/sharing`, payload ); return response.attachment; } /** * Perform bulk attachment operations */ async bulkAttachmentOperations(operation: BulkAttachmentOperation): Promise<{ success: boolean; results: Array<{ attachment_id: string; success: boolean; error?: string; }>; }> { const response = await this.post<{ success: boolean; results: Array<{ attachment_id: string; success: boolean; error?: string; }>; }>('/attachment/bulk', operation); return response; } /** * Get attachment statistics for a workspace */ async getAttachmentStats(workspaceId: string): Promise<AttachmentStatsResponse> { const response = await this.get<AttachmentStatsResponse>(`/team/${workspaceId}/attachment/stats`); return response; } /** * Search attachments across workspace */ async searchAttachments(workspaceId: string, query: { search_term?: string; type?: string; parent_type?: string; tags?: string[]; date_from?: number; date_to?: number; min_size?: number; max_size?: number; uploaded_by?: number; limit?: number; offset?: number; }): Promise<AttachmentListResponse> { const params = new URLSearchParams(); if (query.search_term) params.append('search_term', query.search_term); if (query.type) params.append('type', query.type); if (query.parent_type) params.append('parent_type', query.parent_type); if (query.tags) params.append('tags', query.tags.join(',')); if (query.date_from) params.append('date_from', query.date_from.toString()); if (query.date_to) params.append('date_to', query.date_to.toString()); if (query.min_size) params.append('min_size', query.min_size.toString()); if (query.max_size) params.append('max_size', query.max_size.toString()); if (query.uploaded_by) params.append('uploaded_by', query.uploaded_by.toString()); if (query.limit) params.append('limit', query.limit.toString()); if (query.offset) params.append('offset', query.offset.toString()); const queryString = params.toString(); const endpoint = `/team/${workspaceId}/attachment/search${queryString ? `?${queryString}` : ''}`; const response = await this.get<AttachmentListResponse>(endpoint); return response; } /** * Generate attachment thumbnail */ async generateAttachmentThumbnail(attachmentId: string, options?: { width?: number; height?: number; quality?: number; }): Promise<{ thumbnail_url: string; expires_at: string; }> { const params = new URLSearchParams(); if (options?.width) params.append('width', options.width.toString()); if (options?.height) params.append('height', options.height.toString()); if (options?.quality) params.append('quality', options.quality.toString()); const queryString = params.toString(); const endpoint = `/attachment/${attachmentId}/thumbnail${queryString ? `?${queryString}` : ''}`; const response = await this.post<{ thumbnail_url: string; expires_at: string; }>(endpoint); return response; } /** * Copy attachment to another parent */ async copyAttachment(attachmentId: string, targetParentId: string, targetParentType: string): Promise<AttachmentResponse> { const payload = { target_parent_id: targetParentId, target_parent_type: targetParentType }; const response = await this.post<{ attachment: AttachmentResponse }>( `/attachment/${attachmentId}/copy`, payload ); return response.attachment; } /** * Move attachment to another parent */ async moveAttachment(attachmentId: string, targetParentId: string, targetParentType: string): Promise<AttachmentResponse> { const payload = { target_parent_id: targetParentId, target_parent_type: targetParentType }; const response = await this.put<{ attachment: AttachmentResponse }>( `/attachment/${attachmentId}/move`, payload ); return response.attachment; } /** * Get attachment version history */ async getAttachmentVersions(attachmentId: string): Promise<{ versions: Array<{ version_id: string; version_number: number; filename: string; size: number; date_created: string; uploaded_by: { id: number; username: string; }; is_current: boolean; download_url?: string; }>; }> { const response = await this.get<{ versions: Array<{ version_id: string; version_number: number; filename: string; size: number; date_created: string; uploaded_by: { id: number; username: string; }; is_current: boolean; download_url?: string; }>; }>(`/attachment/${attachmentId}/versions`); return response; } // Helper methods private getParentEndpoint(parentType: string, parentId: string): string { switch (parentType) { case 'task': return `/task/${parentId}`; case 'comment': return `/comment/${parentId}`; case 'doc': return `/doc/${parentId}`; case 'chat': return `/chat/${parentId}`; default: throw new Error(`Invalid parent type: ${parentType}`); } } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Chykalophia/ClickUp-MCP-Server---Enhanced'

If you have feedback or need assistance with the MCP directory API, please join our Discord server