UNPKG

@coretext-ai/qa-gsuite-f47ac10b-58cc-4372-a567-0e02b2c3d479

Version:

MCP server with GSuite (Contacts, Drive, Gmail, Calendar) integration

977 lines 37.9 kB
import { GoogleOAuthClient } from '../oauth/google-oauth-client.js'; export class GoogleDriveClient { constructor() { this.baseUrl = 'https://www.googleapis.com/drive/v3'; // Generate unique session ID for this client instance this.sessionId = `google-drive-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`; this.logDebug('INIT', 'OAuth client instance created', { baseUrl: this.baseUrl, isOAuth: true }); this.oauthClient = new GoogleOAuthClient(); } /** * Get the session ID for this client instance */ getSessionId() { return this.sessionId; } /** * Enhanced debug logging with session context */ logDebug(action, message, metadata) { const timestamp = new Date().toISOString(); const user = process.env.CORETEXT_USER || 'unknown'; const logEntry = { timestamp, sessionId: this.sessionId, user, integration: 'google-drive', component: 'oauth-client', action, message, ...(metadata && { metadata }) }; // Use stderr to avoid MCP protocol interference console.error(`[GOOGLE_DRIVE-OAUTH-CLIENT] ${JSON.stringify(logEntry)}`); } /** * Initialize the API client */ async initialize() { this.logDebug('INITIALIZE', 'Starting OAuth client initialization', { hasOAuthClient: true }); await this.oauthClient.initialize(); this.logDebug('INITIALIZE', 'Google OAuth client initialization completed'); } /** * Make authenticated API request */ async makeRequest(config) { const startTime = Date.now(); this.logDebug('REQUEST_START', 'Making authenticated API request', { method: config.method, path: config.path, hasBody: !!config.body, hasQueryParams: !!config.queryParams }); const accessToken = await this.oauthClient.getValidAccessToken(); this.logDebug('AUTH_TOKEN', 'Retrieved Google OAuth access token', { tokenPreview: accessToken ? accessToken.substring(0, 8) + '...' : 'none' }); const headers = { 'Accept': 'application/json', 'Authorization': `Bearer ${accessToken}`, 'Content-Type': 'application/json', ...config.headers }; const url = this.buildUrl(config.path, config.pathParams, config.queryParams); const response = await fetch(url, { method: config.method, headers, body: config.body ? JSON.stringify(config.body) : undefined }); if (!response.ok) { if (response.status === 401) { // Token might be invalid, try to refresh and retry once await this.oauthClient.getValidAccessToken(); // This will refresh if needed return this.makeRequest(config); // Retry once } const errorText = await response.text(); throw new Error(`API request failed: ${response.status} ${response.statusText} - ${errorText}`); } return response.json(); } /** * Simple upload for files ≤5MB. Upload file content directly */ async uploadFileSimple(args = {}) { const pathParams = {}; const queryParams = { uploadType: args.uploadType, ...(args.name !== undefined && { name: args.name }), ...(args.parents !== undefined && { parents: args.parents }), }; const bodyParams = { fileContent: args.fileContent, }; // Remove undefined values from pathParams Object.keys(pathParams).forEach(key => { if (pathParams[key] === undefined) { delete pathParams[key]; } }); return this.makeRequest({ method: 'POST', path: '/upload/drive/v3/files', pathParams, queryParams: Object.keys(queryParams).length ? queryParams : undefined, body: Object.keys(bodyParams).length ? bodyParams : undefined }); } /** * Multipart upload for files with metadata. Combines metadata and content in single request */ async uploadFileMultipart(args = {}) { const pathParams = {}; const queryParams = { uploadType: args.uploadType, ...(args.fields !== undefined && { fields: args.fields }), }; const bodyParams = { metadata: args.metadata, fileContent: args.fileContent, }; // Remove undefined values from pathParams Object.keys(pathParams).forEach(key => { if (pathParams[key] === undefined) { delete pathParams[key]; } }); return this.makeRequest({ method: 'POST', path: '/upload/drive/v3/files', pathParams, queryParams: Object.keys(queryParams).length ? queryParams : undefined, body: Object.keys(bodyParams).length ? bodyParams : undefined }); } /** * Initiate resumable upload for large files with progress tracking */ async uploadFileResumable(args = {}) { const pathParams = {}; const queryParams = { uploadType: args.uploadType, ...(args.fields !== undefined && { fields: args.fields }), }; const bodyParams = { metadata: args.metadata, }; // Remove undefined values from pathParams Object.keys(pathParams).forEach(key => { if (pathParams[key] === undefined) { delete pathParams[key]; } }); return this.makeRequest({ method: 'POST', path: '/upload/drive/v3/files', pathParams, queryParams: Object.keys(queryParams).length ? queryParams : undefined, body: Object.keys(bodyParams).length ? bodyParams : undefined }); } /** * Get file metadata by ID */ async getFile(args = {}) { const pathParams = { fileId: args.fileId, }; const queryParams = { ...(args.fields !== undefined && { fields: args.fields }), ...(args.supportsAllDrives !== undefined && { supportsAllDrives: args.supportsAllDrives }), ...(args.acknowledgeAbuse !== undefined && { acknowledgeAbuse: args.acknowledgeAbuse }), }; const bodyParams = {}; // Remove undefined values from pathParams Object.keys(pathParams).forEach(key => { if (pathParams[key] === undefined) { delete pathParams[key]; } }); return this.makeRequest({ method: 'GET', path: '/files/{fileId}', pathParams, queryParams: Object.keys(queryParams).length ? queryParams : undefined, body: Object.keys(bodyParams).length ? bodyParams : undefined }); } /** * Download file content or export Google Workspace documents */ async downloadFile(args = {}) { const pathParams = { fileId: args.fileId, }; const queryParams = { alt: args.alt, ...(args.acknowledgeAbuse !== undefined && { acknowledgeAbuse: args.acknowledgeAbuse }), ...(args.supportsAllDrives !== undefined && { supportsAllDrives: args.supportsAllDrives }), }; const bodyParams = {}; // Remove undefined values from pathParams Object.keys(pathParams).forEach(key => { if (pathParams[key] === undefined) { delete pathParams[key]; } }); return this.makeRequest({ method: 'GET', path: '/files/{fileId}', pathParams, queryParams: Object.keys(queryParams).length ? queryParams : undefined, body: Object.keys(bodyParams).length ? bodyParams : undefined }); } /** * Export Google Workspace document to specified format */ async exportFile(args = {}) { const pathParams = { fileId: args.fileId, }; const queryParams = { mimeType: args.mimeType, }; const bodyParams = {}; // Remove undefined values from pathParams Object.keys(pathParams).forEach(key => { if (pathParams[key] === undefined) { delete pathParams[key]; } }); return this.makeRequest({ method: 'GET', path: '/files/{fileId}/export', pathParams, queryParams: Object.keys(queryParams).length ? queryParams : undefined, body: Object.keys(bodyParams).length ? bodyParams : undefined }); } /** * Update file metadata */ async updateFile(args = {}) { const pathParams = { fileId: args.fileId, }; const queryParams = { ...(args.fields !== undefined && { fields: args.fields }), ...(args.supportsAllDrives !== undefined && { supportsAllDrives: args.supportsAllDrives }), }; const bodyParams = { ...(args.name !== undefined && { name: args.name }), ...(args.description !== undefined && { description: args.description }), ...(args.parents !== undefined && { parents: args.parents }), ...(args.starred !== undefined && { starred: args.starred }), ...(args.trashed !== undefined && { trashed: args.trashed }), }; // Remove undefined values from pathParams Object.keys(pathParams).forEach(key => { if (pathParams[key] === undefined) { delete pathParams[key]; } }); return this.makeRequest({ method: 'PATCH', path: '/files/{fileId}', pathParams, queryParams: Object.keys(queryParams).length ? queryParams : undefined, body: Object.keys(bodyParams).length ? bodyParams : undefined }); } /** * Update file content using multipart upload */ async updateFileContent(args = {}) { const pathParams = { fileId: args.fileId, }; const queryParams = { uploadType: args.uploadType, ...(args.fields !== undefined && { fields: args.fields }), }; const bodyParams = { ...(args.metadata !== undefined && { metadata: args.metadata }), fileContent: args.fileContent, }; // Remove undefined values from pathParams Object.keys(pathParams).forEach(key => { if (pathParams[key] === undefined) { delete pathParams[key]; } }); return this.makeRequest({ method: 'PATCH', path: '/upload/drive/v3/files/{fileId}', pathParams, queryParams: Object.keys(queryParams).length ? queryParams : undefined, body: Object.keys(bodyParams).length ? bodyParams : undefined }); } /** * Permanently delete a file */ async deleteFile(args = {}) { const pathParams = { fileId: args.fileId, }; const queryParams = { ...(args.supportsAllDrives !== undefined && { supportsAllDrives: args.supportsAllDrives }), }; const bodyParams = {}; // Remove undefined values from pathParams Object.keys(pathParams).forEach(key => { if (pathParams[key] === undefined) { delete pathParams[key]; } }); return this.makeRequest({ method: 'DELETE', path: '/files/{fileId}', pathParams, queryParams: Object.keys(queryParams).length ? queryParams : undefined, body: Object.keys(bodyParams).length ? bodyParams : undefined }); } /** * Create a copy of an existing file */ async copyFile(args = {}) { const pathParams = { fileId: args.fileId, }; const queryParams = { ...(args.fields !== undefined && { fields: args.fields }), ...(args.supportsAllDrives !== undefined && { supportsAllDrives: args.supportsAllDrives }), }; const bodyParams = { ...(args.name !== undefined && { name: args.name }), ...(args.parents !== undefined && { parents: args.parents }), ...(args.description !== undefined && { description: args.description }), }; // Remove undefined values from pathParams Object.keys(pathParams).forEach(key => { if (pathParams[key] === undefined) { delete pathParams[key]; } }); return this.makeRequest({ method: 'POST', path: '/files/{fileId}/copy', pathParams, queryParams: Object.keys(queryParams).length ? queryParams : undefined, body: Object.keys(bodyParams).length ? bodyParams : undefined }); } /** * Create a new folder */ async createFolder(args = {}) { const pathParams = {}; const queryParams = { ...(args.fields !== undefined && { fields: args.fields }), ...(args.supportsAllDrives !== undefined && { supportsAllDrives: args.supportsAllDrives }), }; const bodyParams = { name: args.name, mimeType: args.mimeType, ...(args.parents !== undefined && { parents: args.parents }), ...(args.description !== undefined && { description: args.description }), ...(args.folderColorRgb !== undefined && { folderColorRgb: args.folderColorRgb }), }; // Remove undefined values from pathParams Object.keys(pathParams).forEach(key => { if (pathParams[key] === undefined) { delete pathParams[key]; } }); return this.makeRequest({ method: 'POST', path: '/files', pathParams, queryParams: Object.keys(queryParams).length ? queryParams : undefined, body: Object.keys(bodyParams).length ? bodyParams : undefined }); } /** * Move a file to different parent folders */ async moveFile(args = {}) { const pathParams = { fileId: args.fileId, }; const queryParams = { ...(args.addParents !== undefined && { addParents: args.addParents }), ...(args.removeParents !== undefined && { removeParents: args.removeParents }), ...(args.fields !== undefined && { fields: args.fields }), ...(args.supportsAllDrives !== undefined && { supportsAllDrives: args.supportsAllDrives }), }; const bodyParams = {}; // Remove undefined values from pathParams Object.keys(pathParams).forEach(key => { if (pathParams[key] === undefined) { delete pathParams[key]; } }); return this.makeRequest({ method: 'PATCH', path: '/files/{fileId}', pathParams, queryParams: Object.keys(queryParams).length ? queryParams : undefined, body: Object.keys(bodyParams).length ? bodyParams : undefined }); } /** * List files and folders within a specific folder */ async getFolderContents(args = {}) { const pathParams = {}; const queryParams = { q: args.q, ...(args.pageSize !== undefined && { pageSize: args.pageSize }), ...(args.pageToken !== undefined && { pageToken: args.pageToken }), ...(args.fields !== undefined && { fields: args.fields }), ...(args.orderBy !== undefined && { orderBy: args.orderBy }), ...(args.supportsAllDrives !== undefined && { supportsAllDrives: args.supportsAllDrives }), ...(args.includeItemsFromAllDrives !== undefined && { includeItemsFromAllDrives: args.includeItemsFromAllDrives }), }; const bodyParams = {}; // Remove undefined values from pathParams Object.keys(pathParams).forEach(key => { if (pathParams[key] === undefined) { delete pathParams[key]; } }); return this.makeRequest({ method: 'GET', path: '/files', pathParams, queryParams: Object.keys(queryParams).length ? queryParams : undefined, body: Object.keys(bodyParams).length ? bodyParams : undefined }); } /** * Get folder hierarchy and structure */ async getFolderTree(args = {}) { const pathParams = {}; const queryParams = { q: args.q, ...(args.pageSize !== undefined && { pageSize: args.pageSize }), ...(args.pageToken !== undefined && { pageToken: args.pageToken }), ...(args.fields !== undefined && { fields: args.fields }), ...(args.orderBy !== undefined && { orderBy: args.orderBy }), ...(args.supportsAllDrives !== undefined && { supportsAllDrives: args.supportsAllDrives }), }; const bodyParams = {}; // Remove undefined values from pathParams Object.keys(pathParams).forEach(key => { if (pathParams[key] === undefined) { delete pathParams[key]; } }); return this.makeRequest({ method: 'GET', path: '/files', pathParams, queryParams: Object.keys(queryParams).length ? queryParams : undefined, body: Object.keys(bodyParams).length ? bodyParams : undefined }); } /** * List files in Google Drive with optional search query and filtering */ async listFiles(args = {}) { const pathParams = {}; const queryParams = { ...(args.q !== undefined && { q: args.q }), ...(args.pageSize !== undefined && { pageSize: args.pageSize }), ...(args.pageToken !== undefined && { pageToken: args.pageToken }), ...(args.fields !== undefined && { fields: args.fields }), ...(args.orderBy !== undefined && { orderBy: args.orderBy }), ...(args.spaces !== undefined && { spaces: args.spaces }), ...(args.corpora !== undefined && { corpora: args.corpora }), ...(args.driveId !== undefined && { driveId: args.driveId }), ...(args.includeItemsFromAllDrives !== undefined && { includeItemsFromAllDrives: args.includeItemsFromAllDrives }), ...(args.supportsAllDrives !== undefined && { supportsAllDrives: args.supportsAllDrives }), ...(args.includePermissionsForView !== undefined && { includePermissionsForView: args.includePermissionsForView }), ...(args.includeLabels !== undefined && { includeLabels: args.includeLabels }), }; const bodyParams = {}; // Remove undefined values from pathParams Object.keys(pathParams).forEach(key => { if (pathParams[key] === undefined) { delete pathParams[key]; } }); return this.makeRequest({ method: 'GET', path: '/files', pathParams, queryParams: Object.keys(queryParams).length ? queryParams : undefined, body: Object.keys(bodyParams).length ? bodyParams : undefined }); } /** * Advanced file search with complex query syntax */ async searchFiles(args = {}) { const pathParams = {}; const queryParams = { q: args.q, ...(args.pageSize !== undefined && { pageSize: args.pageSize }), ...(args.pageToken !== undefined && { pageToken: args.pageToken }), ...(args.fields !== undefined && { fields: args.fields }), ...(args.orderBy !== undefined && { orderBy: args.orderBy }), ...(args.includeItemsFromAllDrives !== undefined && { includeItemsFromAllDrives: args.includeItemsFromAllDrives }), ...(args.supportsAllDrives !== undefined && { supportsAllDrives: args.supportsAllDrives }), }; const bodyParams = {}; // Remove undefined values from pathParams Object.keys(pathParams).forEach(key => { if (pathParams[key] === undefined) { delete pathParams[key]; } }); return this.makeRequest({ method: 'GET', path: '/files', pathParams, queryParams: Object.keys(queryParams).length ? queryParams : undefined, body: Object.keys(bodyParams).length ? bodyParams : undefined }); } /** * List revisions of a specific file */ async listFileRevisions(args = {}) { const pathParams = { fileId: args.fileId, }; const queryParams = { ...(args.pageSize !== undefined && { pageSize: args.pageSize }), ...(args.pageToken !== undefined && { pageToken: args.pageToken }), ...(args.fields !== undefined && { fields: args.fields }), }; const bodyParams = {}; // Remove undefined values from pathParams Object.keys(pathParams).forEach(key => { if (pathParams[key] === undefined) { delete pathParams[key]; } }); return this.makeRequest({ method: 'GET', path: '/files/{fileId}/revisions', pathParams, queryParams: Object.keys(queryParams).length ? queryParams : undefined, body: Object.keys(bodyParams).length ? bodyParams : undefined }); } /** * Get a specific revision of a file */ async getFileRevision(args = {}) { const pathParams = { fileId: args.fileId, revisionId: args.revisionId, }; const queryParams = { ...(args.fields !== undefined && { fields: args.fields }), ...(args.acknowledgeAbuse !== undefined && { acknowledgeAbuse: args.acknowledgeAbuse }), }; const bodyParams = {}; // Remove undefined values from pathParams Object.keys(pathParams).forEach(key => { if (pathParams[key] === undefined) { delete pathParams[key]; } }); return this.makeRequest({ method: 'GET', path: '/files/{fileId}/revisions/{revisionId}', pathParams, queryParams: Object.keys(queryParams).length ? queryParams : undefined, body: Object.keys(bodyParams).length ? bodyParams : undefined }); } /** * Update revision metadata (e.g., set keepForever) */ async updateFileRevision(args = {}) { const pathParams = { fileId: args.fileId, revisionId: args.revisionId, }; const queryParams = { ...(args.fields !== undefined && { fields: args.fields }), }; const bodyParams = { ...(args.keepForever !== undefined && { keepForever: args.keepForever }), ...(args.publishAuto !== undefined && { publishAuto: args.publishAuto }), ...(args.published !== undefined && { published: args.published }), }; // Remove undefined values from pathParams Object.keys(pathParams).forEach(key => { if (pathParams[key] === undefined) { delete pathParams[key]; } }); return this.makeRequest({ method: 'PATCH', path: '/files/{fileId}/revisions/{revisionId}', pathParams, queryParams: Object.keys(queryParams).length ? queryParams : undefined, body: Object.keys(bodyParams).length ? bodyParams : undefined }); } /** * Delete a specific revision of a file */ async deleteFileRevision(args = {}) { const pathParams = { fileId: args.fileId, revisionId: args.revisionId, }; const queryParams = {}; const bodyParams = {}; // Remove undefined values from pathParams Object.keys(pathParams).forEach(key => { if (pathParams[key] === undefined) { delete pathParams[key]; } }); return this.makeRequest({ method: 'DELETE', path: '/files/{fileId}/revisions/{revisionId}', pathParams, queryParams: Object.keys(queryParams).length ? queryParams : undefined, body: Object.keys(bodyParams).length ? bodyParams : undefined }); } /** * Create a permission for a file or folder (sharing) */ async createPermission(args = {}) { const pathParams = { fileId: args.fileId, }; const queryParams = { ...(args.sendNotificationEmail !== undefined && { sendNotificationEmail: args.sendNotificationEmail }), ...(args.emailMessage !== undefined && { emailMessage: args.emailMessage }), ...(args.transferOwnership !== undefined && { transferOwnership: args.transferOwnership }), ...(args.moveToNewOwnersRoot !== undefined && { moveToNewOwnersRoot: args.moveToNewOwnersRoot }), ...(args.supportsAllDrives !== undefined && { supportsAllDrives: args.supportsAllDrives }), ...(args.fields !== undefined && { fields: args.fields }), }; const bodyParams = { role: args.role, type: args.type, ...(args.emailAddress !== undefined && { emailAddress: args.emailAddress }), ...(args.domain !== undefined && { domain: args.domain }), ...(args.allowFileDiscovery !== undefined && { allowFileDiscovery: args.allowFileDiscovery }), ...(args.expirationTime !== undefined && { expirationTime: args.expirationTime }), }; // Remove undefined values from pathParams Object.keys(pathParams).forEach(key => { if (pathParams[key] === undefined) { delete pathParams[key]; } }); return this.makeRequest({ method: 'POST', path: '/files/{fileId}/permissions', pathParams, queryParams: Object.keys(queryParams).length ? queryParams : undefined, body: Object.keys(bodyParams).length ? bodyParams : undefined }); } /** * List permissions for a file or folder */ async listPermissions(args = {}) { const pathParams = { fileId: args.fileId, }; const queryParams = { ...(args.pageSize !== undefined && { pageSize: args.pageSize }), ...(args.pageToken !== undefined && { pageToken: args.pageToken }), ...(args.fields !== undefined && { fields: args.fields }), ...(args.supportsAllDrives !== undefined && { supportsAllDrives: args.supportsAllDrives }), ...(args.useDomainAdminAccess !== undefined && { useDomainAdminAccess: args.useDomainAdminAccess }), ...(args.includePermissionsForView !== undefined && { includePermissionsForView: args.includePermissionsForView }), }; const bodyParams = {}; // Remove undefined values from pathParams Object.keys(pathParams).forEach(key => { if (pathParams[key] === undefined) { delete pathParams[key]; } }); return this.makeRequest({ method: 'GET', path: '/files/{fileId}/permissions', pathParams, queryParams: Object.keys(queryParams).length ? queryParams : undefined, body: Object.keys(bodyParams).length ? bodyParams : undefined }); } /** * Get a specific permission for a file */ async getPermission(args = {}) { const pathParams = { fileId: args.fileId, permissionId: args.permissionId, }; const queryParams = { ...(args.fields !== undefined && { fields: args.fields }), ...(args.supportsAllDrives !== undefined && { supportsAllDrives: args.supportsAllDrives }), ...(args.useDomainAdminAccess !== undefined && { useDomainAdminAccess: args.useDomainAdminAccess }), }; const bodyParams = {}; // Remove undefined values from pathParams Object.keys(pathParams).forEach(key => { if (pathParams[key] === undefined) { delete pathParams[key]; } }); return this.makeRequest({ method: 'GET', path: '/files/{fileId}/permissions/{permissionId}', pathParams, queryParams: Object.keys(queryParams).length ? queryParams : undefined, body: Object.keys(bodyParams).length ? bodyParams : undefined }); } /** * Update an existing permission */ async updatePermission(args = {}) { const pathParams = { fileId: args.fileId, permissionId: args.permissionId, }; const queryParams = { ...(args.transferOwnership !== undefined && { transferOwnership: args.transferOwnership }), ...(args.removeExpiration !== undefined && { removeExpiration: args.removeExpiration }), ...(args.supportsAllDrives !== undefined && { supportsAllDrives: args.supportsAllDrives }), ...(args.fields !== undefined && { fields: args.fields }), }; const bodyParams = { ...(args.role !== undefined && { role: args.role }), ...(args.expirationTime !== undefined && { expirationTime: args.expirationTime }), }; // Remove undefined values from pathParams Object.keys(pathParams).forEach(key => { if (pathParams[key] === undefined) { delete pathParams[key]; } }); return this.makeRequest({ method: 'PATCH', path: '/files/{fileId}/permissions/{permissionId}', pathParams, queryParams: Object.keys(queryParams).length ? queryParams : undefined, body: Object.keys(bodyParams).length ? bodyParams : undefined }); } /** * Remove a permission from a file or folder */ async deletePermission(args = {}) { const pathParams = { fileId: args.fileId, permissionId: args.permissionId, }; const queryParams = { ...(args.supportsAllDrives !== undefined && { supportsAllDrives: args.supportsAllDrives }), ...(args.useDomainAdminAccess !== undefined && { useDomainAdminAccess: args.useDomainAdminAccess }), }; const bodyParams = {}; // Remove undefined values from pathParams Object.keys(pathParams).forEach(key => { if (pathParams[key] === undefined) { delete pathParams[key]; } }); return this.makeRequest({ method: 'DELETE', path: '/files/{fileId}/permissions/{permissionId}', pathParams, queryParams: Object.keys(queryParams).length ? queryParams : undefined, body: Object.keys(bodyParams).length ? bodyParams : undefined }); } /** * Create a comment on a file */ async createComment(args = {}) { const pathParams = { fileId: args.fileId, }; const queryParams = { ...(args.fields !== undefined && { fields: args.fields }), }; const bodyParams = { content: args.content, ...(args.anchor !== undefined && { anchor: args.anchor }), ...(args.quotedFileContent !== undefined && { quotedFileContent: args.quotedFileContent }), }; // Remove undefined values from pathParams Object.keys(pathParams).forEach(key => { if (pathParams[key] === undefined) { delete pathParams[key]; } }); return this.makeRequest({ method: 'POST', path: '/files/{fileId}/comments', pathParams, queryParams: Object.keys(queryParams).length ? queryParams : undefined, body: Object.keys(bodyParams).length ? bodyParams : undefined }); } /** * List comments on a file */ async listComments(args = {}) { const pathParams = { fileId: args.fileId, }; const queryParams = { ...(args.pageSize !== undefined && { pageSize: args.pageSize }), ...(args.pageToken !== undefined && { pageToken: args.pageToken }), ...(args.fields !== undefined && { fields: args.fields }), ...(args.includeDeleted !== undefined && { includeDeleted: args.includeDeleted }), ...(args.startModifiedTime !== undefined && { startModifiedTime: args.startModifiedTime }), }; const bodyParams = {}; // Remove undefined values from pathParams Object.keys(pathParams).forEach(key => { if (pathParams[key] === undefined) { delete pathParams[key]; } }); return this.makeRequest({ method: 'GET', path: '/files/{fileId}/comments', pathParams, queryParams: Object.keys(queryParams).length ? queryParams : undefined, body: Object.keys(bodyParams).length ? bodyParams : undefined }); } /** * Get a specific comment */ async getComment(args = {}) { const pathParams = { fileId: args.fileId, commentId: args.commentId, }; const queryParams = { ...(args.fields !== undefined && { fields: args.fields }), ...(args.includeDeleted !== undefined && { includeDeleted: args.includeDeleted }), }; const bodyParams = {}; // Remove undefined values from pathParams Object.keys(pathParams).forEach(key => { if (pathParams[key] === undefined) { delete pathParams[key]; } }); return this.makeRequest({ method: 'GET', path: '/files/{fileId}/comments/{commentId}', pathParams, queryParams: Object.keys(queryParams).length ? queryParams : undefined, body: Object.keys(bodyParams).length ? bodyParams : undefined }); } /** * Update a comment */ async updateComment(args = {}) { const pathParams = { fileId: args.fileId, commentId: args.commentId, }; const queryParams = { ...(args.fields !== undefined && { fields: args.fields }), }; const bodyParams = { ...(args.content !== undefined && { content: args.content }), }; // Remove undefined values from pathParams Object.keys(pathParams).forEach(key => { if (pathParams[key] === undefined) { delete pathParams[key]; } }); return this.makeRequest({ method: 'PATCH', path: '/files/{fileId}/comments/{commentId}', pathParams, queryParams: Object.keys(queryParams).length ? queryParams : undefined, body: Object.keys(bodyParams).length ? bodyParams : undefined }); } /** * Delete a comment */ async deleteComment(args = {}) { const pathParams = { fileId: args.fileId, commentId: args.commentId, }; const queryParams = {}; const bodyParams = {}; // Remove undefined values from pathParams Object.keys(pathParams).forEach(key => { if (pathParams[key] === undefined) { delete pathParams[key]; } }); return this.makeRequest({ method: 'DELETE', path: '/files/{fileId}/comments/{commentId}', pathParams, queryParams: Object.keys(queryParams).length ? queryParams : undefined, body: Object.keys(bodyParams).length ? bodyParams : undefined }); } /** * Build URL with path parameters and query string */ buildUrl(path, pathParams, queryParams) { let url = this.baseUrl + path; // Replace path parameters if (pathParams) { for (const [key, value] of Object.entries(pathParams)) { url = url.replace(`{${key}}`, encodeURIComponent(String(value))); } } // Add query parameters if (queryParams && Object.keys(queryParams).length > 0) { const searchParams = new URLSearchParams(); for (const [key, value] of Object.entries(queryParams)) { if (value !== undefined && value !== null) { searchParams.append(key, String(value)); } } const queryString = searchParams.toString(); if (queryString) { url += `?${queryString}`; } } return url; } /** * Check if client is authenticated */ async isAuthenticated() { return this.oauthClient.isAuthenticated(); } /** * Revoke authentication tokens */ async revokeAuthentication() { await this.oauthClient.revokeTokens(); } } //# sourceMappingURL=google-drive-client.js.map