solver-sdk
Version:
SDK для интеграции с Code Solver Backend API
315 lines • 13.6 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.FileSystemWsClient = void 0;
const base_ws_client_1 = require("./base-ws-client");
const websocket_namespaces_constants_1 = require("../constants/websocket-namespaces.constants");
const websocket_events_constants_1 = require("../constants/websocket-events.constants");
const uuid_1 = require("uuid");
/**
* Клиент WebSocket для работы с файловой системой
*/
class FileSystemWsClient extends base_ws_client_1.BaseWebSocketClient {
/**
* Создает новый клиент для работы с файловой системой
* @param baseURL Базовый URL API
* @param options Опции клиента
*/
constructor(baseURL, options = {}) {
super(websocket_namespaces_constants_1.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(websocket_events_constants_1.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(websocket_events_constants_1.WebSocketEvents.READ_FILE, async (request) => {
try {
const content = await this.onReadFile(request.payload.path);
this.send(websocket_events_constants_1.WebSocketEvents.READ_FILE_RESPONSE, {
requestId: request.requestId,
projectId: request.projectId,
payload: { content }
});
}
catch (error) {
this.send(websocket_events_constants_1.WebSocketEvents.ERROR, {
requestId: request.requestId,
error: {
code: 'FILE_READ_ERROR',
message: error instanceof Error ? error.message : String(error)
}
});
}
});
// Обработчик запроса на получение списка файлов
this.on(websocket_events_constants_1.WebSocketEvents.LIST_FILES, async (request) => {
try {
const files = await this.onListFiles(request.payload.directory, request.payload.options);
this.send(websocket_events_constants_1.WebSocketEvents.LIST_FILES_RESPONSE, {
requestId: request.requestId,
projectId: request.projectId,
payload: {
files,
directory: request.payload.directory
}
});
}
catch (error) {
this.send(websocket_events_constants_1.WebSocketEvents.ERROR, {
requestId: request.requestId,
error: {
code: 'LIST_FILES_ERROR',
message: error instanceof Error ? error.message : String(error)
}
});
}
});
// Обработчик запроса на отслеживание файлов
this.on(websocket_events_constants_1.WebSocketEvents.WATCH_START, async (request) => {
try {
const success = await this.onWatchStart(request.payload.patterns);
this.send(websocket_events_constants_1.WebSocketEvents.WATCH_CONFIRM, {
requestId: request.requestId,
projectId: request.projectId,
payload: {
success,
patterns: request.payload.patterns
}
});
}
catch (error) {
this.send(websocket_events_constants_1.WebSocketEvents.ERROR, {
requestId: request.requestId,
error: {
code: 'WATCH_ERROR',
message: error instanceof Error ? error.message : String(error)
}
});
}
});
// Обработчик ping
this.on(websocket_events_constants_1.WebSocketEvents.PING, (data) => {
this.send(websocket_events_constants_1.WebSocketEvents.PONG, {
requestId: data.requestId || (0, uuid_1.v4)(),
timestamp: Date.now()
});
});
}
/**
* Уведомляет сервер об изменении файла
* @param path Путь к файлу
* @param changeType Тип изменения
*/
notifyFileChanged(path, changeType = 'modified') {
if (!this.isConnected() || !this.projectId) {
return false;
}
return this.send(websocket_events_constants_1.WebSocketEvents.FILE_CHANGED, {
requestId: (0, uuid_1.v4)(),
projectId: this.projectId,
payload: {
path,
changeType,
timestamp: Date.now()
}
});
}
}
exports.FileSystemWsClient = FileSystemWsClient;
/**
* Пример использования клиента файловой системы в 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