UNPKG

solver-sdk

Version:

SDK for WorkAI API - AI-powered code analysis with WorkCoins billing system

329 lines 13.4 kB
/** * API для работы с проектами */ export class ProjectsApi { constructor(httpClient) { this.httpClient = httpClient; } // ===== ОСНОВНЫЕ МЕТОДЫ УПРАВЛЕНИЯ ПРОЕКТАМИ ===== /** * Получает все проекты пользователя * * @returns {Promise<Project[] | null>} Массив проектов или null при auth ошибках (401/403) * * @example * ```typescript * const projects = await sdk.projects.getAllProjects(); * if (!projects) { * // Auth error - токен истек * await authManager.refreshToken(); * return; * } * ``` */ async getAllProjects() { const projects = await this.httpClient.get('/api/v1/projects'); return projects; } /** * Альтернативное имя для getAllProjects() для совместимости * * @returns {Promise<Project[] | null>} Массив проектов или null при auth ошибках (401/403) */ async getProjects() { return this.getAllProjects(); } /** * Находит или создает проект по имени * * @param {string} projectName Имя проекта * @returns {Promise<Project | null>} Проект или null при auth ошибках (401/403) * * @example * ```typescript * const project = await sdk.projects.findOrCreateProject('MyProject'); * if (!project) { * // Auth error - токен истек * return; * } * console.log(project.id); * ``` */ async findOrCreateProject(projectName) { if (!projectName?.trim()) { throw new Error('Project name is required'); } const response = await this.httpClient.post('/api/v1/projects/find-or-create', { name: projectName.trim() }); return response; } /** * Получает проекты, готовые к использованию * * @returns {Promise<Project[] | null>} Массив проектов или null при auth ошибках (401/403) */ async getReadyProjects() { const allProjects = await this.getAllProjects(); if (!allProjects) return null; return allProjects.filter(project => project.indexStatus === 'indexed'); } /** * Получает проект по ID * * @param {string} projectId ID проекта * @returns {Promise<Project | null>} Проект или null при auth ошибках (401/403) */ async getProject(projectId) { this.validateProjectId(projectId); const project = await this.httpClient.get(`/api/v1/projects/${projectId}`); return project; } /** * Создает новый проект * * @param {string} name Имя проекта * @param {any} data Дополнительные данные * @param {ProjectOptions} options Опции проекта * @returns {Promise<Project | null>} Созданный проект или null при auth ошибках (401/403) */ async createProject(name, data, options) { if (!name?.trim()) { throw new Error('Project name is required'); } const requestData = { name: name.trim(), ...data, ...options }; const project = await this.httpClient.post('/api/v1/projects', requestData); return project; } /** * Удаляет проект */ async deleteProject(projectId) { this.validateProjectId(projectId); await this.httpClient.delete(`/api/v1/projects/${projectId}`); } // ===== ИНДЕКСАЦИЯ И СТАТУС ===== /** * Получает статус проекта * * @param {string} projectId ID проекта * @returns {Promise<any | null>} Статус проекта или null при auth ошибках (401/403) */ async getProjectStatus(projectId) { this.validateProjectId(projectId); return await this.httpClient.get(`/api/v1/projects/${projectId}/status`); } /** * Получает статус индексации проекта * * @param {string} projectId ID проекта * @returns {Promise<any | null>} Статус индексации или null при auth ошибках (401/403) */ async getIndexingStatus(projectId) { this.validateProjectId(projectId); return await this.httpClient.get(`/api/v1/projects/${projectId}/indexing-status`); } /** * Отменяет индексацию проекта * * @param {string} projectId ID проекта * @returns {Promise<boolean | null>} true если отменено, false при ошибке, null при auth ошибке (401/403) */ async cancelIndexing(projectId) { this.validateProjectId(projectId); try { const result = await this.httpClient.post(`/api/v1/projects/${projectId}/cancel-indexing`); if (result === null) return null; // Auth error return true; } catch (error) { console.error('Failed to cancel indexing:', error); return false; } } /** * Очищает ошибку индексации * * @param {string} projectId ID проекта * @returns {Promise<boolean | null>} true если очищено, false при ошибке, null при auth ошибке (401/403) */ async clearIndexingError(projectId) { this.validateProjectId(projectId); try { const result = await this.httpClient.post(`/api/v1/projects/${projectId}/clear-error`); if (result === null) return null; // Auth error return true; } catch (error) { console.error('Failed to clear indexing error:', error); return false; } } // ===== DELTA CHUNKING УДАЛЕНЫ ===== // Ручные методы sendInitialSync/sendDeltaSync/finalizeDeltaSync удалены // ✅ ИСПОЛЬЗУЙТЕ: sdk.deltaManager.syncEncryptedChunks() - делает всё автоматически // ===== PROJECT STATE И SMART SYNC ===== /** * Получение состояния проекта с проверкой синхронизации * * @param projectId - ID проекта * @param clientRootHash - Merkle root hash клиента для проверки необходимости синхронизации * @returns ProjectState с полем syncRequired (всегда присутствует в response) * @throws Error если backend не вернул обязательное поле syncRequired */ async getProjectState(projectId, clientRootHash) { this.validateProjectId(projectId); const url = clientRootHash ? `/api/v1/projects/${projectId}/state?clientRootHash=${encodeURIComponent(clientRootHash)}` : `/api/v1/projects/${projectId}/state`; const response = await this.httpClient.get(url); // Валидация: syncRequired ДОЛЖНО присутствовать в response if (response.syncRequired === undefined || response.syncRequired === null) { throw new Error(`Backend did not return required field 'syncRequired' for project ${projectId}. ` + `This indicates a backend version mismatch or API error. ` + `Response: ${JSON.stringify(response)}`); } return { projectId: response.projectId || projectId, projectName: response.projectName || 'Unknown', merkleRootHash: response.merkleRootHash || null, lastIndexedAt: response.lastIndexedAt ? new Date(response.lastIndexedAt) : null, totalChunks: response.totalChunks || 0, totalFiles: response.totalFiles || 0, indexingStatus: response.indexingStatus || 'unknown', syncRequired: response.syncRequired, lastSyncSessionId: response.lastSyncSessionId }; } // ===== SESSION RECOVERY ===== /** * Получение статуса восстановления сессии */ async getRecoveryStatus(projectId) { this.validateProjectId(projectId); const response = await this.httpClient.get(`/api/v1/projects/${projectId}/recovery-status`); return { hasInterruptedSession: response.hasInterruptedSession || false, recoveryInfo: response.recoveryInfo ? { sessionId: response.recoveryInfo.sessionId, projectId: response.recoveryInfo.projectId || projectId, projectName: response.recoveryInfo.projectName || 'Unknown', status: response.recoveryInfo.status || 'interrupted', progress: { received: response.recoveryInfo.progress?.totalChunks || 0, processed: response.recoveryInfo.progress?.processedChunks || 0, total: response.recoveryInfo.progress?.totalChunks || 0, percentage: response.recoveryInfo.progress?.percentage || 0 }, interruptedAt: response.recoveryInfo.lastActivity ? new Date(response.recoveryInfo.lastActivity) : new Date(), resumeReason: response.recoveryInfo.resumeReason || 'session_recovery', canResume: response.recoveryInfo.canResume !== false } : undefined }; } /** * Восстановление прерванной синхронизации */ async resumeSync(projectId, options = {}) { this.validateProjectId(projectId); const response = await this.httpClient.post(`/api/v1/projects/${projectId}/resume-sync`, { skipDuplicates: options.skipDuplicates !== false, continueFromLastBatch: options.continueFromLastBatch !== false }); return { success: response.success !== false, message: response.message, continueFromBatch: response.continueFromBatch, sessionId: response.sessionId }; } /** * Отмена восстановления сессии */ async cancelRecovery(projectId) { this.validateProjectId(projectId); const response = await this.httpClient.delete(`/api/v1/projects/${projectId}/recovery`); return { success: response.success !== false, message: response.message }; } /** * Инициализация Delta Sync */ async initializeDeltaSync(projectId, clientRootHash) { this.validateProjectId(projectId); if (!clientRootHash?.trim()) { throw new Error('Client root hash is required'); } const response = await this.httpClient.post(`/api/v1/projects/${projectId}/initialize-delta-sync`, { clientRootHash: clientRootHash.trim() }); return { needsSync: response.needsSync !== false, sessionId: response.sessionId, lastSyncHash: response.lastSyncHash }; } /** * Сброс индексации проекта */ async resetIndexing(projectId) { this.validateProjectId(projectId); const response = await this.httpClient.post(`/api/v1/projects/${projectId}/reset-indexing`); return { success: response.success !== false, message: response.message || 'Reset completed', clearedChunks: response.clearedChunks, clearedFiles: response.clearedFiles }; } /** * Перезапуск индексации проекта */ async restartIndexing(projectId) { this.validateProjectId(projectId); const response = await this.httpClient.post(`/api/v1/projects/${projectId}/restart-indexing`); return { success: response.success !== false, message: response.message || 'Restart initiated', newSessionId: response.newSessionId }; } /** * Получение маппинга файловых путей */ async getFilePathMapping(projectId) { this.validateProjectId(projectId); const response = await this.httpClient.get(`/api/v1/projects/${projectId}/file-path-mapping`); return { success: response.success !== false, mapping: response.mapping || [], totalFiles: response.totalFiles || 0 }; } // ===== УТИЛИТЫ ===== /** * Валидация ID проекта * @private */ validateProjectId(projectId) { if (projectId === undefined || projectId === null) { throw new Error('Project ID is required'); } if (typeof projectId !== 'string') { throw new Error('Project ID must be a string'); } if (projectId.trim().length === 0) { throw new Error('Project ID cannot be empty'); } } } //# sourceMappingURL=projects-api.js.map