UNPKG

solver-sdk

Version:

SDK для интеграции с Code Solver Backend API

311 lines 13 kB
import { BaseWebSocketClient } from './base-ws-client'; import { WebSocketNamespace } from '../constants/websocket-namespaces.constants'; import { WebSocketEvents } from '../constants/websocket-events.constants'; import { v4 as uuidv4 } from 'uuid'; /** * Клиент WebSocket для работы с файловой системой */ export class FileSystemWsClient extends BaseWebSocketClient { /** * Создает новый клиент для работы с файловой системой * @param baseURL Базовый URL API * @param options Опции клиента */ constructor(baseURL, options = {}) { super(WebSocketNamespace.FILESYSTEM, baseURL, { enableAutoPing: true, pingInterval: 25000, reconnectStrategy: 'exponential', retryDelay: 1000, maxRetryDelay: 30000 }); this.sessionId = null; this.projectId = null; this.pingInterval = 25000; // 25 секунд по умолчанию this.pingTimer = null; this.SDK_VERSION = '1.0.0'; // Устанавливаем обработчики this.onReadFile = options.onReadFile || (() => Promise.reject('Чтение файлов не реализовано')); this.onListFiles = options.onListFiles || (() => Promise.reject('Получение списка файлов не реализовано')); this.onWatchStart = options.onWatchStart || (() => Promise.reject('Отслеживание файлов не реализовано')); } /** * Подключение к серверу и инициализация сессии * @param params Параметры подключения (может содержать projectId или другие параметры) * @returns Promise<boolean> Успешность подключения */ async connect(params = {}) { // Если передан projectId, сохраняем его if (params.projectId) { this.projectId = params.projectId; } // Проверяем, есть ли у нас projectId if (!this.projectId) { this.logger.error('Не указан projectId для подключения'); return false; } // Подключаемся с базовыми параметрами const connected = await super.connect(params); if (!connected) { return false; } try { // Инициализируем сессию const response = await this.emitWithAck(WebSocketEvents.INIT, { projectId: this.projectId, clientVersion: this.SDK_VERSION, capabilities: ['text', 'watch'] }); if (response && response.payload) { this.sessionId = response.payload.sessionId; this.pingInterval = response.payload.pingInterval || 25000; // Настраиваем обработчики событий this.setupHandlers(); return true; } else { this.logger.error('Ошибка инициализации сессии: Пустой ответ'); return false; } } catch (error) { this.logger.error(`Ошибка инициализации сессии: ${error instanceof Error ? error.message : String(error)}`); return false; } } /** * Подключение к проекту - удобный метод для использования в приложении * @param projectId ID проекта * @returns Promise<boolean> Успешность подключения */ async connectToProject(projectId) { this.projectId = projectId; return this.connect({ projectId }); } /** * Настройка обработчиков событий */ setupHandlers() { // Обработчик запроса на чтение файла this.on(WebSocketEvents.READ_FILE, async (request) => { try { const content = await this.onReadFile(request.payload.path); this.send(WebSocketEvents.READ_FILE_RESPONSE, { requestId: request.requestId, projectId: request.projectId, payload: { content } }); } catch (error) { this.send(WebSocketEvents.ERROR, { requestId: request.requestId, error: { code: 'FILE_READ_ERROR', message: error instanceof Error ? error.message : String(error) } }); } }); // Обработчик запроса на получение списка файлов this.on(WebSocketEvents.LIST_FILES, async (request) => { try { const files = await this.onListFiles(request.payload.directory, request.payload.options); this.send(WebSocketEvents.LIST_FILES_RESPONSE, { requestId: request.requestId, projectId: request.projectId, payload: { files, directory: request.payload.directory } }); } catch (error) { this.send(WebSocketEvents.ERROR, { requestId: request.requestId, error: { code: 'LIST_FILES_ERROR', message: error instanceof Error ? error.message : String(error) } }); } }); // Обработчик запроса на отслеживание файлов this.on(WebSocketEvents.WATCH_START, async (request) => { try { const success = await this.onWatchStart(request.payload.patterns); this.send(WebSocketEvents.WATCH_CONFIRM, { requestId: request.requestId, projectId: request.projectId, payload: { success, patterns: request.payload.patterns } }); } catch (error) { this.send(WebSocketEvents.ERROR, { requestId: request.requestId, error: { code: 'WATCH_ERROR', message: error instanceof Error ? error.message : String(error) } }); } }); // Обработчик ping this.on(WebSocketEvents.PING, (data) => { this.send(WebSocketEvents.PONG, { requestId: data.requestId || uuidv4(), timestamp: Date.now() }); }); } /** * Уведомляет сервер об изменении файла * @param path Путь к файлу * @param changeType Тип изменения */ notifyFileChanged(path, changeType = 'modified') { if (!this.isConnected() || !this.projectId) { return false; } return this.send(WebSocketEvents.FILE_CHANGED, { requestId: uuidv4(), projectId: this.projectId, payload: { path, changeType, timestamp: Date.now() } }); } } /** * Пример использования клиента файловой системы в VS Code расширении: * * ```typescript * import * as vscode from 'vscode'; * import { FileSystemWsClient } from 'solver-sdk'; * * export function activate(context: vscode.ExtensionContext) { * // Создание клиента файловой системы * const fsClient = new FileSystemWsClient('wss://your-backend-url.com', { * // Обработчик чтения файла * onReadFile: async (path) => { * try { * const uri = vscode.Uri.file(path); * const content = await vscode.workspace.fs.readFile(uri); * return new TextDecoder().decode(content); * } catch (error) { * throw new Error(`Ошибка чтения файла: ${error.message}`); * } * }, * * // Обработчик получения списка файлов * onListFiles: async (directory, options) => { * try { * // Получаем корневую директорию рабочего пространства * const rootPath = vscode.workspace.workspaceFolders?.[0]?.uri.fsPath; * if (!rootPath) throw new Error('Не найдено рабочее пространство'); * * // Формируем паттерн для поиска файлов * const pattern = new vscode.RelativePattern( * rootPath, * options?.includePatterns?.[0] || '**' * ); * * // Находим файлы по паттерну * const files = await vscode.workspace.findFiles(pattern, * options?.excludePatterns?.join('|') * ); * * // Преобразуем результаты в нужный формат * return files.map(uri => { * const relativePath = vscode.workspace.asRelativePath(uri); * const stats = fs.statSync(uri.fsPath); * * return { * path: uri.fsPath, * relativePath, * extension: uri.fsPath.split('.').pop() || '', * size: stats.size, * isDirectory: stats.isDirectory() * }; * }); * } catch (error) { * throw new Error(`Ошибка получения списка файлов: ${error.message}`); * } * }, * * // Обработчик отслеживания файлов * onWatchStart: async (patterns) => { * try { * // Создаем наблюдателей за файлами * const watchers = patterns.map(pattern => { * const watcher = vscode.workspace.createFileSystemWatcher( * new vscode.RelativePattern( * vscode.workspace.workspaceFolders?.[0]?.uri.fsPath || '', * pattern * ) * ); * * // Обработчик изменения файла * watcher.onDidChange(uri => { * const relativePath = vscode.workspace.asRelativePath(uri); * fsClient.notifyFileChanged(relativePath, 'modified'); * }); * * // Обработчик создания файла * watcher.onDidCreate(uri => { * const relativePath = vscode.workspace.asRelativePath(uri); * fsClient.notifyFileChanged(relativePath, 'created'); * }); * * // Обработчик удаления файла * watcher.onDidDelete(uri => { * const relativePath = vscode.workspace.asRelativePath(uri); * fsClient.notifyFileChanged(relativePath, 'deleted'); * }); * * return watcher; * }); * * // Добавляем наблюдателей в контекст расширения для правильной очистки * watchers.forEach(watcher => { * context.subscriptions.push(watcher); * }); * * return true; * } catch (error) { * console.error('Ошибка при настройке отслеживания файлов:', error); * return false; * } * } * }); * * // Подключаемся к проекту * vscode.commands.registerCommand('extension.connectToProject', async () => { * // Запрашиваем ID проекта у пользователя * const projectId = await vscode.window.showInputBox({ * prompt: 'Введите ID проекта для подключения' * }); * * if (!projectId) return; * * try { * // Устанавливаем соединение * const connected = await fsClient.connectToProject(projectId); * * if (connected) { * vscode.window.showInformationMessage(`Успешное подключение к проекту ${projectId}`); * } else { * vscode.window.showErrorMessage('Ошибка подключения к проекту'); * } * } catch (error) { * vscode.window.showErrorMessage(`Ошибка: ${error.message}`); * } * }); * } * ``` */ //# sourceMappingURL=filesystem-ws-client.js.map