solver-sdk
Version:
SDK for WorkAI API - AI-powered code analysis with WorkCoins billing system
284 lines • 10.4 kB
JavaScript
/**
* 🔄 Update Manager - Helper для управления обновлениями на стороне клиента
*
* Этот класс НЕ является частью SDK API, а предоставляет удобные helper методы
* для интеграции с electron-updater и управления локальным состоянием обновлений.
*
* @example
* ```typescript
* import { CodeSolverSDK, UpdateManager } from 'solver-sdk';
*
* const sdk = new CodeSolverSDK({ baseURL: 'https://workai.su' });
* const updateManager = new UpdateManager(sdk.updates, {
* autoCheckOnStart: true,
* autoDownload: false,
* showNotifications: true
* });
*
* // Подписка на события
* updateManager.on('update-available', (info) => {
* console.log(`Доступна версия ${info.version}`);
* });
*
* updateManager.on('download-progress', (progress) => {
* console.log(`Загружено: ${progress.percent}%`);
* });
*
* // Проверка обновлений
* await updateManager.checkForUpdates('1.0.0', 'win32-x64');
*
* // Получение текущего состояния
* const state = updateManager.getCurrentState();
* ```
*/
export class UpdateManager {
/**
* Создает новый UpdateManager
*
* @param updatesApi Экземпляр UpdatesApi из SDK
* @param config Конфигурация для автообновлений
*/
constructor(updatesApi, config = {}) {
// Локальное состояние
this.state = {
status: 'idle',
updateInfo: null,
progress: null,
error: null,
lastChecked: null
};
// Event listeners
this.listeners = new Map();
this.updatesApi = updatesApi;
this.config = {
autoCheckOnStart: false,
autoCheckInterval: 4 * 60 * 60 * 1000, // 4 часа по умолчанию
autoDownload: false,
autoInstallOnAppQuit: false,
showNotifications: true,
...config
};
// Запускаем автопроверку если включена
if (this.config.autoCheckOnStart) {
this.startAutoCheck();
}
}
/**
* 🔍 Проверка наличия обновлений
*
* @param currentVersion Текущая версия приложения
* @param platform Платформа (win32-x64, darwin-x64, linux-x64)
* @param channel Канал обновлений (stable, beta, insider)
* @returns Информация об обновлении или null если обновлений нет
*/
async checkForUpdates(currentVersion, platform, channel = 'stable') {
this.updateState({ status: 'checking', error: null });
this.emit('checking-for-update');
try {
const updateInfo = await this.updatesApi.checkForUpdates({
currentVersion,
platform,
channel,
locale: 'ru'
});
this.updateState({
lastChecked: new Date(),
status: 'idle'
});
if (updateInfo.hasUpdate) {
this.updateState({
status: 'available',
updateInfo
});
this.emit('update-available', updateInfo);
// Автозагрузка если включена
if (this.config.autoDownload) {
// Примечание: фактическая загрузка должна быть реализована через electron-updater
// Здесь просто уведомляем о необходимости загрузки
this.emit('auto-download-requested', updateInfo);
}
return updateInfo;
}
else {
this.emit('update-not-available');
return null;
}
}
catch (error) {
this.updateState({
status: 'error',
error: error.message
});
this.emit('error', error);
throw error;
}
}
/**
* 📊 Получение текущего состояния обновлений
*
* @returns Текущее состояние
*/
getCurrentState() {
return { ...this.state };
}
/**
* 📊 Получение текущего статуса (для совместимости с клиентом)
*
* @returns Объект с текущим статусом
*/
getCurrentStatus() {
return {
status: this.state.status,
updateInfo: this.state.updateInfo,
progress: this.state.progress
};
}
/**
* 🔄 Обновление прогресса загрузки (вызывается из electron-updater)
*
* @param progress Информация о прогрессе
*/
updateDownloadProgress(progress) {
this.updateState({
status: 'downloading',
progress
});
this.emit('download-progress', progress);
}
/**
* ✅ Уведомление о завершении загрузки (вызывается из electron-updater)
*/
markDownloadCompleted() {
this.updateState({
status: 'downloaded',
progress: { percent: 100, transferred: 0, total: 0 }
});
this.emit('update-downloaded', this.state.updateInfo);
// Отправляем статистику на бэкенд
if (this.state.updateInfo) {
this.updatesApi.sendStats({
event: 'update_completed',
currentVersion: this.state.updateInfo.version || 'unknown',
targetVersion: this.state.updateInfo.version || 'unknown'
}).catch(err => console.warn('Failed to send update stats:', err));
}
}
/**
* ❌ Уведомление об ошибке загрузки (вызывается из electron-updater)
*
* @param error Сообщение об ошибке
*/
markDownloadError(error) {
this.updateState({
status: 'error',
error
});
this.emit('error', new Error(error));
// Отправляем статистику на бэкенд
if (this.state.updateInfo) {
this.updatesApi.sendStats({
event: 'update_failed',
currentVersion: this.state.updateInfo.version || 'unknown',
targetVersion: this.state.updateInfo.version || 'unknown',
error
}).catch(err => console.warn('Failed to send update stats:', err));
}
}
/**
* 📝 Получение changelog для версии
*
* @param version Версия для получения changelog
* @param locale Локаль (по умолчанию 'ru')
* @returns Markdown текст с описанием изменений
*/
async getChangelog(version, locale = 'ru') {
return await this.updatesApi.getChangelog(version, locale);
}
/**
* 🔔 Подписка на события
*
* @param event Название события
* @param listener Функция-обработчик
*
* События:
* - checking-for-update: Начата проверка обновлений
* - update-available: Обновление доступно
* - update-not-available: Обновлений нет
* - download-progress: Прогресс загрузки
* - update-downloaded: Загрузка завершена
* - error: Произошла ошибка
* - auto-download-requested: Запрошена автозагрузка
*/
on(event, listener) {
if (!this.listeners.has(event)) {
this.listeners.set(event, new Set());
}
this.listeners.get(event).add(listener);
}
/**
* 🔕 Отписка от события
*
* @param event Название события
* @param listener Функция-обработчик
*/
off(event, listener) {
const eventListeners = this.listeners.get(event);
if (eventListeners) {
eventListeners.delete(listener);
}
}
/**
* 🔄 Запуск автоматической проверки обновлений
*/
startAutoCheck() {
if (this.autoCheckTimer) {
clearInterval(this.autoCheckTimer);
}
if (this.config.autoCheckInterval && this.config.autoCheckInterval > 0) {
this.autoCheckTimer = setInterval(() => {
// Автопроверка требует знания текущей версии и платформы
// Эти данные должны быть предоставлены через событие
this.emit('auto-check-requested');
}, this.config.autoCheckInterval);
}
}
/**
* 🛑 Остановка автоматической проверки обновлений
*/
stopAutoCheck() {
if (this.autoCheckTimer) {
clearInterval(this.autoCheckTimer);
this.autoCheckTimer = undefined;
}
}
/**
* 🧹 Очистка ресурсов
*/
dispose() {
this.stopAutoCheck();
this.listeners.clear();
}
/**
* Обновление внутреннего состояния
*/
updateState(partialState) {
this.state = { ...this.state, ...partialState };
}
/**
* Генерация события
*/
emit(event, data) {
const eventListeners = this.listeners.get(event);
if (eventListeners) {
eventListeners.forEach(listener => {
try {
listener(data);
}
catch (error) {
console.error(`Error in event listener for ${event}:`, error);
}
});
}
}
}
//# sourceMappingURL=update-manager.js.map