UNPKG

solver-sdk

Version:

SDK для интеграции с Code Solver Backend API (совместимо с браузером и Node.js), с поддержкой функциональности мышления (Thinking Mode)

313 lines 13.6 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ProjectsApi = exports.ApiEndpoints = void 0; const code_solver_websocket_client_js_1 = require("../utils/code-solver-websocket-client.js"); /** * Константы для API путей */ var ApiEndpoints; (function (ApiEndpoints) { ApiEndpoints["PROJECTS"] = "/api/v1/projects"; ApiEndpoints["PROJECT"] = "/api/v1/projects/:id"; ApiEndpoints["PROJECT_INDEXING_STATUS"] = "/api/v1/projects/:id/indexing_status"; ApiEndpoints["PROJECT_CANCEL_INDEXING"] = "/api/v1/projects/:id/cancel_indexing"; ApiEndpoints["PROJECT_CLEAR_ERROR"] = "/api/v1/projects/:id/clear_error"; })(ApiEndpoints || (exports.ApiEndpoints = ApiEndpoints = {})); /** * Замещает параметры в пути API * @param endpoint Шаблон пути API * @param params Параметры для замещения * @returns Путь API с замещенными параметрами */ function formatEndpoint(endpoint, params) { let result = endpoint; for (const [key, value] of Object.entries(params)) { result = result.replace(`:${key}`, value); } return result; } /** * API для работы с проектами */ class ProjectsApi { /** * Создает новый экземпляр API для работы с проектами * @param {HttpClient} httpClient HTTP клиент */ constructor(httpClient) { /** WebSocket клиент */ this.wsClient = null; /** Родительский SDK */ this.parentSdk = null; this.httpClient = httpClient; } /** * Проверяет валидность идентификатора проекта * @param {string} projectId ID проекта * @throws {Error} Если ID проекта не валиден */ 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() === '') { throw new Error('Project ID cannot be empty'); } } /** * Получает список всех проектов * @returns {Promise<Project[]>} Список проектов */ async getAllProjects() { return this.httpClient.get('/api/v1/projects'); } /** * Получает проект по ID * @param {string} projectId ID проекта * @returns {Promise<Project>} Проект */ async getProject(projectId) { this.validateProjectId(projectId); return this.httpClient.get('/api/v1/projects/' + projectId); } /** * Создает новый проект * @param {string} name Название проекта * @param {string} path Путь к проекту * @param {ProjectOptions} [options] Дополнительные опции проекта * @returns {Promise<Project>} Созданный проект */ async createProject(name, path, options) { return this.httpClient.post('/api/v1/projects', { name, path, ...options }); } /** * Обновляет проект * @param {string} projectId ID проекта * @param {Partial<ProjectUpdateData>} data Данные для обновления * @returns {Promise<Project>} Обновленный проект */ async updateProject(projectId, data) { this.validateProjectId(projectId); return this.httpClient.put('/api/v1/projects/' + projectId, data); } /** * Удаляет проект * @param {string} projectId ID проекта * @returns {Promise<void>} */ async deleteProject(projectId) { this.validateProjectId(projectId); return this.httpClient.delete('/api/v1/projects/' + projectId); } /** * Запускает индексацию проекта * @param {string} projectId ID проекта * @returns {Promise<IndexingResponse>} Информация о начатой индексации */ async indexProject(projectId) { this.validateProjectId(projectId); return this.httpClient.post('/api/v1/projects/' + projectId + '/index'); } /** * Получает статус индексации проекта * @param {string} projectId Идентификатор проекта * @returns {Promise<any>} Статус индексации проекта */ async getIndexingStatus(projectId) { this.validateProjectId(projectId); return this.httpClient.get(formatEndpoint(ApiEndpoints.PROJECT_INDEXING_STATUS, { id: projectId })); } /** * Отменяет индексацию проекта * @param {string} projectId Идентификатор проекта * @returns {Promise<boolean>} Результат отмены индексации */ async cancelIndexing(projectId) { if (!projectId) { throw new Error('Project ID is required'); } return this.httpClient.post(formatEndpoint(ApiEndpoints.PROJECT_CANCEL_INDEXING, { id: projectId })) .then(response => { return true; }) .catch(error => { throw new Error(`Failed to cancel indexing: ${error.message}`); }); } /** * Очищает ошибку индексации проекта * @param {string} projectId Идентификатор проекта * @returns {Promise<boolean>} Результат очистки ошибки */ async clearIndexingError(projectId) { this.validateProjectId(projectId); return this.httpClient.post(formatEndpoint(ApiEndpoints.PROJECT_CLEAR_ERROR, { id: projectId })) .then(() => true) .catch(error => { throw new Error(`Failed to clear indexing error: ${error.message}`); }); } /** * Обновляет индекс конкретного файла в проекте * @param {string} projectId ID проекта * @param {string} filePath Путь к файлу (относительно корня проекта) * @param {Object} options Опции обновления индекса * @param {string} [options.content] Содержимое файла (если не указано, будет прочитано с диска) * @param {boolean} [options.force=false] Принудительная переиндексация, даже если файл не изменился * @returns {Promise<FileIndexResponse>} Информация об обновленном индексе файла */ async updateFileIndex(projectId, filePath, options = {}) { this.validateProjectId(projectId); if (!filePath) { throw new Error('Путь к файлу не может быть пустым'); } // Кодируем путь для URL, чтобы избежать проблем со специальными символами const encodedFilePath = encodeURIComponent(filePath); return this.httpClient.post('/api/v1/projects/' + projectId + '/files/' + encodedFilePath + '/index', options); } /** * Подключается к WebSocket для событий индексации * @returns {Promise<boolean>} Результат подключения */ async connectWebSocket() { try { if (!this.parentSdk || typeof this.parentSdk.getWebSocketClient !== 'function') { throw new Error('Родительский SDK не настроен или не поддерживает WebSocket'); } this.wsClient = this.parentSdk.getWebSocketClient(); await this.wsClient.connectToIndexing(); return this.wsClient.isConnected('indexing'); } catch (error) { console.error('[ProjectsApi] Ошибка при подключении к WebSocket:', error.message); return false; } } /** * Отключается от WebSocket для событий индексации * @returns {Promise<void>} */ async disconnectWebSocket() { if (this.wsClient) { await this.wsClient.disconnect('indexing'); } } /** * Проверяет, подключен ли WebSocket * @returns {boolean} Состояние подключения */ isWebSocketConnected() { return this.wsClient ? this.wsClient.isConnected('indexing') : false; } /** * Устанавливает родительский SDK * @param sdk Родительский SDK */ setParent(sdk) { this.parentSdk = sdk; } /** * Подписывается на событие через WebSocket * @param event Название события * @param callback Функция обратного вызова */ on(event, callback) { if (!this.wsClient) { console.warn('[ProjectsApi] WebSocket не подключен'); return; } this.wsClient.on(event, callback); } /** * Отправляет событие через WebSocket * @param event Название события * @param data Данные для отправки */ emitSocketEvent(event, data) { if (!this.wsClient) { console.warn('[ProjectsApi] WebSocket не подключен'); return; } this.wsClient.send(code_solver_websocket_client_js_1.WebSocketNamespace.INDEXING, event, data); } /** * Отправляет событие через WebSocket с ожиданием ответа * @param event Имя события * @param data Данные для отправки * @param timeout Таймаут ожидания ответа * @returns {Promise<any>} Ответ от сервера */ async sendSocketEventWithResponse(event, data, timeout = 5000) { if (!this.wsClient) { throw new Error('[ProjectsApi] WebSocket не подключен'); } // Реализуем собственный механизм emitWithAck, если wsClient не поддерживает его return new Promise((resolve, reject) => { try { // Создаем уникальный ID для запроса const requestId = `req_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`; // Имя события для ответа const responseEvent = `${event}_response`; // Обработчик для получения ответа const responseHandler = (response) => { if (response && response.requestId === requestId) { // Очищаем таймер и удаляем обработчик clearTimeout(timeoutId); if (this.wsClient) { this.wsClient.off(responseEvent, responseHandler); } // Разрешаем промис с ответом resolve(response.data || response); } }; // Устанавливаем таймаут const timeoutId = setTimeout(() => { if (this.wsClient) { this.wsClient.off(responseEvent, responseHandler); } reject(new Error(`Таймаут ожидания ответа на событие ${event}`)); }, timeout); // Регистрируем обработчик this.wsClient.on(responseEvent, responseHandler); // Отправляем событие this.wsClient.send(code_solver_websocket_client_js_1.WebSocketNamespace.INDEXING, event, { ...data, requestId }); } catch (error) { reject(error); } }); } /** * Остановить индексацию проекта через WebSocket * @param projectId ID проекта * @returns {Promise<boolean>} Результат операции */ async stopIndexing(projectId) { this.validateProjectId(projectId); try { if (!this.wsClient || !this.isWebSocketConnected()) { // Если WebSocket не доступен, используем REST API return this.cancelIndexing(projectId); } const result = await this.sendSocketEventWithResponse('STOP_INDEXING', { projectId }, 5000); return result && result.success === true; } catch (error) { console.error('[ProjectsApi] Ошибка при остановке индексации:', error.message); // Пробуем через REST API как запасной вариант return this.cancelIndexing(projectId); } } } exports.ProjectsApi = ProjectsApi; //# sourceMappingURL=projects-api.js.map