@alphamatica/app-updater 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +46 -0
- package/LICENSE +21 -0
- package/README.md +186 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +23 -0
- package/dist/index.js.map +1 -0
- package/dist/types.d.ts +36 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/dist/ui.d.ts +21 -0
- package/dist/ui.d.ts.map +1 -0
- package/dist/ui.js +166 -0
- package/dist/ui.js.map +1 -0
- package/dist/updater.d.ts +19 -0
- package/dist/updater.d.ts.map +1 -0
- package/dist/updater.js +213 -0
- package/dist/updater.js.map +1 -0
- package/package.json +55 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [1.0.0] - 2024-12-14
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- Initial release
|
|
13
|
+
- `Updater` class for checking, downloading, and installing updates
|
|
14
|
+
- `UpdaterUI` class for showing update dialogs in Electron
|
|
15
|
+
- Support for multiple platforms: Windows, macOS, Linux
|
|
16
|
+
- Support for multiple architectures: x64, arm64, ia32
|
|
17
|
+
- Support for multiple file types: zip, tar.gz, AppImage, exe, dmg
|
|
18
|
+
- Automatic update checking with configurable interval
|
|
19
|
+
- Download progress tracking
|
|
20
|
+
- Server-controlled updates and downgrades
|
|
21
|
+
- Event-based API for update lifecycle
|
|
22
|
+
- TypeScript support with full type definitions
|
|
23
|
+
|
|
24
|
+
### Features
|
|
25
|
+
|
|
26
|
+
- **Updater**
|
|
27
|
+
- `checkForUpdates()` - Check for available updates
|
|
28
|
+
- `downloadUpdate()` - Download the update file
|
|
29
|
+
- `installUpdate()` - Install update and restart application
|
|
30
|
+
- `startAutoCheck()` / `stopAutoCheck()` - Automatic periodic checking
|
|
31
|
+
- Event emitter for update lifecycle events
|
|
32
|
+
|
|
33
|
+
- **UpdaterUI**
|
|
34
|
+
- Native Electron dialogs for update notifications
|
|
35
|
+
- Progress dialog during download
|
|
36
|
+
- Confirmation dialogs for install/restart
|
|
37
|
+
|
|
38
|
+
### Configuration
|
|
39
|
+
|
|
40
|
+
- `serverUrl` - URL of the A-Updater server
|
|
41
|
+
- `appSlug` - Application identifier
|
|
42
|
+
- `currentVersion` - Current application version
|
|
43
|
+
- `channel` - Update channel (default: 'stable')
|
|
44
|
+
- `autoDownload` - Automatically download updates
|
|
45
|
+
- `autoInstall` - Automatically install updates
|
|
46
|
+
- `checkInterval` - Interval for automatic checking (ms)
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Alphamatica
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
# @alphamatica/app-updater
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@alphamatica/app-updater)
|
|
4
|
+
[](https://www.npmjs.com/package/@alphamatica/app-updater)
|
|
5
|
+
[](https://www.npmjs.com/package/@alphamatica/app-updater)
|
|
6
|
+
|
|
7
|
+
Клиентский пакет для интеграции автоматических обновлений в Electron приложения.
|
|
8
|
+
|
|
9
|
+
## Установка
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
yarn add @alphamatica/app-updater
|
|
13
|
+
# или
|
|
14
|
+
npm install @alphamatica/app-updater
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Использование
|
|
18
|
+
|
|
19
|
+
### Базовый пример
|
|
20
|
+
|
|
21
|
+
```typescript
|
|
22
|
+
import { Updater } from '@alphamatica/app-updater';
|
|
23
|
+
import { app } from 'electron';
|
|
24
|
+
|
|
25
|
+
const updater = new Updater({
|
|
26
|
+
serverUrl: 'https://updates.example.com',
|
|
27
|
+
appSlug: 'my-app',
|
|
28
|
+
currentVersion: app.getVersion(),
|
|
29
|
+
channel: 'stable', // опционально, по умолчанию 'stable'
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
// События
|
|
33
|
+
updater.on('checking-for-update', () => {
|
|
34
|
+
console.log('Проверка обновлений...');
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
updater.on('update-available', (info) => {
|
|
38
|
+
console.log(`Доступна версия ${info.version}`);
|
|
39
|
+
console.log(`Размер: ${info.fileSize} байт`);
|
|
40
|
+
console.log(`Даунгрейд: ${info.isDowngrade}`);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
updater.on('update-not-available', () => {
|
|
44
|
+
console.log('Обновлений нет');
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
updater.on('download-progress', (progress) => {
|
|
48
|
+
console.log(`Загрузка: ${progress.percent}%`);
|
|
49
|
+
console.log(`Скорость: ${progress.bytesPerSecond} B/s`);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
updater.on('update-downloaded', (info) => {
|
|
53
|
+
console.log(`Версия ${info.version} загружена`);
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
updater.on('error', (error) => {
|
|
57
|
+
console.error('Ошибка:', error.message);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
// Проверить обновления
|
|
61
|
+
await updater.checkForUpdates();
|
|
62
|
+
|
|
63
|
+
// Скачать обновление
|
|
64
|
+
await updater.downloadUpdate();
|
|
65
|
+
|
|
66
|
+
// Установить и перезапустить
|
|
67
|
+
await updater.installUpdate();
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### С UI компонентом
|
|
71
|
+
|
|
72
|
+
```typescript
|
|
73
|
+
import { Updater, UpdaterUI } from '@alphamatica/app-updater';
|
|
74
|
+
|
|
75
|
+
const updater = new Updater({
|
|
76
|
+
serverUrl: 'https://updates.example.com',
|
|
77
|
+
appSlug: 'my-app',
|
|
78
|
+
currentVersion: app.getVersion(),
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
const ui = new UpdaterUI({
|
|
82
|
+
updater,
|
|
83
|
+
showNotification: true, // показывать диалоги
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
// Проверит обновления и покажет диалог если есть
|
|
87
|
+
await ui.checkForUpdates();
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### Автоматическая проверка
|
|
91
|
+
|
|
92
|
+
```typescript
|
|
93
|
+
const updater = new Updater({
|
|
94
|
+
serverUrl: 'https://updates.example.com',
|
|
95
|
+
appSlug: 'my-app',
|
|
96
|
+
currentVersion: app.getVersion(),
|
|
97
|
+
checkInterval: 60 * 60 * 1000, // каждый час
|
|
98
|
+
autoDownload: true, // автоматически скачивать
|
|
99
|
+
autoInstall: false, // НЕ устанавливать автоматически
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
// Запустить периодическую проверку
|
|
103
|
+
updater.startAutoCheck();
|
|
104
|
+
|
|
105
|
+
// Остановить
|
|
106
|
+
updater.stopAutoCheck();
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## API
|
|
110
|
+
|
|
111
|
+
### Updater
|
|
112
|
+
|
|
113
|
+
#### Конструктор
|
|
114
|
+
|
|
115
|
+
```typescript
|
|
116
|
+
new Updater(config: UpdaterConfig)
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
**UpdaterConfig:**
|
|
120
|
+
- `serverUrl` (string) - URL сервера обновлений
|
|
121
|
+
- `appSlug` (string) - slug приложения
|
|
122
|
+
- `currentVersion` (string) - текущая версия
|
|
123
|
+
- `channel` (string, optional) - канал обновлений, по умолчанию 'stable'
|
|
124
|
+
- `autoDownload` (boolean, optional) - автоматически скачивать
|
|
125
|
+
- `autoInstall` (boolean, optional) - автоматически устанавливать
|
|
126
|
+
- `checkInterval` (number, optional) - интервал проверки в мс
|
|
127
|
+
|
|
128
|
+
#### Методы
|
|
129
|
+
|
|
130
|
+
- `checkForUpdates(): Promise<UpdateInfo>` - проверить обновления
|
|
131
|
+
- `downloadUpdate(): Promise<string>` - скачать обновление
|
|
132
|
+
- `installUpdate(): Promise<void>` - установить и перезапустить
|
|
133
|
+
- `startAutoCheck(): void` - запустить периодическую проверку
|
|
134
|
+
- `stopAutoCheck(): void` - остановить периодическую проверку
|
|
135
|
+
- `getUpdateInfo(): UpdateInfo | null` - получить информацию об обновлении
|
|
136
|
+
|
|
137
|
+
#### События
|
|
138
|
+
|
|
139
|
+
- `checking-for-update` - начало проверки
|
|
140
|
+
- `update-available` - обновление доступно
|
|
141
|
+
- `update-not-available` - обновлений нет
|
|
142
|
+
- `download-progress` - прогресс загрузки
|
|
143
|
+
- `update-downloaded` - загрузка завершена
|
|
144
|
+
- `error` - ошибка
|
|
145
|
+
|
|
146
|
+
### UpdaterUI
|
|
147
|
+
|
|
148
|
+
#### Конструктор
|
|
149
|
+
|
|
150
|
+
```typescript
|
|
151
|
+
new UpdaterUI(options: UpdaterUIOptions)
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
**UpdaterUIOptions:**
|
|
155
|
+
- `updater` (Updater) - экземпляр Updater
|
|
156
|
+
- `showNotification` (boolean, optional) - показывать диалоги
|
|
157
|
+
|
|
158
|
+
#### Методы
|
|
159
|
+
|
|
160
|
+
- `checkForUpdates(): Promise<void>` - проверить и показать UI
|
|
161
|
+
|
|
162
|
+
## Типы
|
|
163
|
+
|
|
164
|
+
```typescript
|
|
165
|
+
interface UpdateInfo {
|
|
166
|
+
updateAvailable: boolean;
|
|
167
|
+
version?: string;
|
|
168
|
+
notes?: string;
|
|
169
|
+
downloadUrl?: string;
|
|
170
|
+
fileName?: string;
|
|
171
|
+
fileSize?: number;
|
|
172
|
+
checksum?: string;
|
|
173
|
+
isDowngrade?: boolean;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
interface DownloadProgress {
|
|
177
|
+
percent: number;
|
|
178
|
+
transferred: number;
|
|
179
|
+
total: number;
|
|
180
|
+
bytesPerSecond: number;
|
|
181
|
+
}
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## Лицензия
|
|
185
|
+
|
|
186
|
+
MIT
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,OAAO,EAAE,SAAS,EAAE,MAAM,MAAM,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.Updater = exports.UpdaterUI = void 0;
|
|
18
|
+
__exportStar(require("./types"), exports);
|
|
19
|
+
var ui_1 = require("./ui");
|
|
20
|
+
Object.defineProperty(exports, "UpdaterUI", { enumerable: true, get: function () { return ui_1.UpdaterUI; } });
|
|
21
|
+
var updater_1 = require("./updater");
|
|
22
|
+
Object.defineProperty(exports, "Updater", { enumerable: true, get: function () { return updater_1.Updater; } });
|
|
23
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,0CAAwB;AACxB,2BAAiC;AAAxB,+FAAA,SAAS,OAAA;AAClB,qCAAoC;AAA3B,kGAAA,OAAO,OAAA"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export interface UpdaterConfig {
|
|
2
|
+
serverUrl: string;
|
|
3
|
+
appSlug: string;
|
|
4
|
+
currentVersion: string;
|
|
5
|
+
channel?: string;
|
|
6
|
+
autoDownload?: boolean;
|
|
7
|
+
autoInstall?: boolean;
|
|
8
|
+
checkInterval?: number;
|
|
9
|
+
}
|
|
10
|
+
export interface UpdateInfo {
|
|
11
|
+
updateAvailable: boolean;
|
|
12
|
+
version?: string;
|
|
13
|
+
notes?: string;
|
|
14
|
+
downloadUrl?: string;
|
|
15
|
+
fileName?: string;
|
|
16
|
+
fileSize?: number;
|
|
17
|
+
checksum?: string;
|
|
18
|
+
isDowngrade?: boolean;
|
|
19
|
+
}
|
|
20
|
+
export interface DownloadProgress {
|
|
21
|
+
percent: number;
|
|
22
|
+
transferred: number;
|
|
23
|
+
total: number;
|
|
24
|
+
bytesPerSecond: number;
|
|
25
|
+
}
|
|
26
|
+
export type Platform = 'linux' | 'win32' | 'darwin';
|
|
27
|
+
export type Arch = 'x64' | 'arm64' | 'ia32';
|
|
28
|
+
export interface UpdaterEvents {
|
|
29
|
+
'checking-for-update': () => void;
|
|
30
|
+
'update-available': (info: UpdateInfo) => void;
|
|
31
|
+
'update-not-available': () => void;
|
|
32
|
+
'download-progress': (progress: DownloadProgress) => void;
|
|
33
|
+
'update-downloaded': (info: UpdateInfo) => void;
|
|
34
|
+
error: (error: Error) => void;
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,UAAU;IACzB,eAAe,EAAE,OAAO,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,OAAO,GAAG,QAAQ,CAAC;AACpD,MAAM,MAAM,IAAI,GAAG,KAAK,GAAG,OAAO,GAAG,MAAM,CAAC;AAE5C,MAAM,WAAW,aAAa;IAC5B,qBAAqB,EAAE,MAAM,IAAI,CAAC;IAClC,kBAAkB,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,IAAI,CAAC;IAC/C,sBAAsB,EAAE,MAAM,IAAI,CAAC;IACnC,mBAAmB,EAAE,CAAC,QAAQ,EAAE,gBAAgB,KAAK,IAAI,CAAC;IAC1D,mBAAmB,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,IAAI,CAAC;IAChD,KAAK,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CAC/B"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
package/dist/ui.d.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Updater } from './updater';
|
|
2
|
+
export interface UpdaterUIOptions {
|
|
3
|
+
updater: Updater;
|
|
4
|
+
autoCheck?: boolean;
|
|
5
|
+
showNotification?: boolean;
|
|
6
|
+
}
|
|
7
|
+
export declare class UpdaterUI {
|
|
8
|
+
private updater;
|
|
9
|
+
private progressWindow;
|
|
10
|
+
private options;
|
|
11
|
+
constructor(options: UpdaterUIOptions);
|
|
12
|
+
private setupListeners;
|
|
13
|
+
private setupIPC;
|
|
14
|
+
private showUpdateDialog;
|
|
15
|
+
private showInstallDialog;
|
|
16
|
+
private showProgressWindow;
|
|
17
|
+
private updateProgress;
|
|
18
|
+
private closeProgressWindow;
|
|
19
|
+
checkForUpdates(): Promise<void>;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=ui.d.ts.map
|
package/dist/ui.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ui.d.ts","sourceRoot":"","sources":["../src/ui.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED,qBAAa,SAAS;IACpB,OAAO,CAAC,OAAO,CAAU;IACzB,OAAO,CAAC,cAAc,CAA8B;IACpD,OAAO,CAAC,OAAO,CAA6B;gBAEhC,OAAO,EAAE,gBAAgB;IAYrC,OAAO,CAAC,cAAc;IAoBtB,OAAO,CAAC,QAAQ;YAkBF,gBAAgB;YAiBhB,iBAAiB;IAkB/B,OAAO,CAAC,kBAAkB;IA4E1B,OAAO,CAAC,cAAc;IAMtB,OAAO,CAAC,mBAAmB;IAOrB,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC;CAGvC"}
|
package/dist/ui.js
ADDED
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.UpdaterUI = void 0;
|
|
4
|
+
const electron_1 = require("electron");
|
|
5
|
+
class UpdaterUI {
|
|
6
|
+
constructor(options) {
|
|
7
|
+
this.progressWindow = null;
|
|
8
|
+
this.options = {
|
|
9
|
+
autoCheck: true,
|
|
10
|
+
showNotification: true,
|
|
11
|
+
...options,
|
|
12
|
+
};
|
|
13
|
+
this.updater = options.updater;
|
|
14
|
+
this.setupListeners();
|
|
15
|
+
this.setupIPC();
|
|
16
|
+
}
|
|
17
|
+
setupListeners() {
|
|
18
|
+
this.updater.on('update-available', info => {
|
|
19
|
+
if (this.options.showNotification) {
|
|
20
|
+
this.showUpdateDialog(info);
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
this.updater.on('download-progress', progress => {
|
|
24
|
+
this.updateProgress(progress);
|
|
25
|
+
});
|
|
26
|
+
this.updater.on('update-downloaded', info => {
|
|
27
|
+
this.showInstallDialog(info);
|
|
28
|
+
});
|
|
29
|
+
this.updater.on('error', error => {
|
|
30
|
+
electron_1.dialog.showErrorBox('Ошибка обновления', error.message);
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
setupIPC() {
|
|
34
|
+
electron_1.ipcMain.handle('updater:check', async () => {
|
|
35
|
+
return this.updater.checkForUpdates();
|
|
36
|
+
});
|
|
37
|
+
electron_1.ipcMain.handle('updater:download', async () => {
|
|
38
|
+
return this.updater.downloadUpdate();
|
|
39
|
+
});
|
|
40
|
+
electron_1.ipcMain.handle('updater:install', async () => {
|
|
41
|
+
return this.updater.installUpdate();
|
|
42
|
+
});
|
|
43
|
+
electron_1.ipcMain.handle('updater:getInfo', () => {
|
|
44
|
+
return this.updater.getUpdateInfo();
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
async showUpdateDialog(info) {
|
|
48
|
+
const result = await electron_1.dialog.showMessageBox({
|
|
49
|
+
type: 'info',
|
|
50
|
+
title: 'Доступно обновление',
|
|
51
|
+
message: `Доступна новая версия ${info.version}`,
|
|
52
|
+
detail: info.notes || 'Хотите скачать обновление?',
|
|
53
|
+
buttons: ['Скачать', 'Позже'],
|
|
54
|
+
defaultId: 0,
|
|
55
|
+
cancelId: 1,
|
|
56
|
+
});
|
|
57
|
+
if (result.response === 0) {
|
|
58
|
+
this.showProgressWindow();
|
|
59
|
+
await this.updater.downloadUpdate();
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
async showInstallDialog(info) {
|
|
63
|
+
this.closeProgressWindow();
|
|
64
|
+
const result = await electron_1.dialog.showMessageBox({
|
|
65
|
+
type: 'info',
|
|
66
|
+
title: 'Обновление загружено',
|
|
67
|
+
message: `Версия ${info.version} готова к установке`,
|
|
68
|
+
detail: 'Приложение будет перезапущено для завершения обновления.',
|
|
69
|
+
buttons: ['Установить сейчас', 'Позже'],
|
|
70
|
+
defaultId: 0,
|
|
71
|
+
cancelId: 1,
|
|
72
|
+
});
|
|
73
|
+
if (result.response === 0) {
|
|
74
|
+
await this.updater.installUpdate();
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
showProgressWindow() {
|
|
78
|
+
this.progressWindow = new electron_1.BrowserWindow({
|
|
79
|
+
width: 400,
|
|
80
|
+
height: 150,
|
|
81
|
+
resizable: false,
|
|
82
|
+
minimizable: false,
|
|
83
|
+
maximizable: false,
|
|
84
|
+
closable: false,
|
|
85
|
+
frame: false,
|
|
86
|
+
alwaysOnTop: true,
|
|
87
|
+
webPreferences: {
|
|
88
|
+
nodeIntegration: true,
|
|
89
|
+
contextIsolation: false,
|
|
90
|
+
},
|
|
91
|
+
});
|
|
92
|
+
const html = `
|
|
93
|
+
<!DOCTYPE html>
|
|
94
|
+
<html>
|
|
95
|
+
<head>
|
|
96
|
+
<style>
|
|
97
|
+
body {
|
|
98
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
99
|
+
margin: 0;
|
|
100
|
+
padding: 20px;
|
|
101
|
+
background: #fff;
|
|
102
|
+
display: flex;
|
|
103
|
+
flex-direction: column;
|
|
104
|
+
justify-content: center;
|
|
105
|
+
}
|
|
106
|
+
h3 { margin: 0 0 15px 0; font-size: 16px; }
|
|
107
|
+
.progress-bar {
|
|
108
|
+
width: 100%;
|
|
109
|
+
height: 20px;
|
|
110
|
+
background: #e0e0e0;
|
|
111
|
+
border-radius: 10px;
|
|
112
|
+
overflow: hidden;
|
|
113
|
+
}
|
|
114
|
+
.progress-fill {
|
|
115
|
+
height: 100%;
|
|
116
|
+
background: linear-gradient(90deg, #1890ff, #40a9ff);
|
|
117
|
+
transition: width 0.3s;
|
|
118
|
+
}
|
|
119
|
+
.progress-text {
|
|
120
|
+
margin-top: 10px;
|
|
121
|
+
font-size: 14px;
|
|
122
|
+
color: #666;
|
|
123
|
+
}
|
|
124
|
+
</style>
|
|
125
|
+
</head>
|
|
126
|
+
<body>
|
|
127
|
+
<h3>Загрузка обновления...</h3>
|
|
128
|
+
<div class="progress-bar">
|
|
129
|
+
<div class="progress-fill" id="progress" style="width: 0%"></div>
|
|
130
|
+
</div>
|
|
131
|
+
<div class="progress-text" id="text">0%</div>
|
|
132
|
+
<script>
|
|
133
|
+
const { ipcRenderer } = require('electron');
|
|
134
|
+
ipcRenderer.on('progress', (e, data) => {
|
|
135
|
+
document.getElementById('progress').style.width = data.percent + '%';
|
|
136
|
+
document.getElementById('text').textContent =
|
|
137
|
+
data.percent + '% (' + formatBytes(data.transferred) + ' / ' + formatBytes(data.total) + ')';
|
|
138
|
+
});
|
|
139
|
+
function formatBytes(bytes) {
|
|
140
|
+
if (bytes < 1024) return bytes + ' B';
|
|
141
|
+
if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + ' KB';
|
|
142
|
+
return (bytes / (1024 * 1024)).toFixed(1) + ' MB';
|
|
143
|
+
}
|
|
144
|
+
</script>
|
|
145
|
+
</body>
|
|
146
|
+
</html>
|
|
147
|
+
`;
|
|
148
|
+
this.progressWindow.loadURL(`data:text/html;charset=utf-8,${encodeURIComponent(html)}`);
|
|
149
|
+
}
|
|
150
|
+
updateProgress(progress) {
|
|
151
|
+
if (this.progressWindow && !this.progressWindow.isDestroyed()) {
|
|
152
|
+
this.progressWindow.webContents.send('progress', progress);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
closeProgressWindow() {
|
|
156
|
+
if (this.progressWindow && !this.progressWindow.isDestroyed()) {
|
|
157
|
+
this.progressWindow.close();
|
|
158
|
+
this.progressWindow = null;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
async checkForUpdates() {
|
|
162
|
+
await this.updater.checkForUpdates();
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
exports.UpdaterUI = UpdaterUI;
|
|
166
|
+
//# sourceMappingURL=ui.js.map
|
package/dist/ui.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ui.js","sourceRoot":"","sources":["../src/ui.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { EventEmitter } from 'events';
|
|
2
|
+
import { UpdateInfo, UpdaterConfig, UpdaterEvents } from './types';
|
|
3
|
+
export declare class Updater extends EventEmitter {
|
|
4
|
+
private config;
|
|
5
|
+
private client;
|
|
6
|
+
private updateInfo;
|
|
7
|
+
private downloadedFile;
|
|
8
|
+
private checkTimer;
|
|
9
|
+
constructor(config: UpdaterConfig);
|
|
10
|
+
on<K extends keyof UpdaterEvents>(event: K, listener: UpdaterEvents[K]): this;
|
|
11
|
+
emit<K extends keyof UpdaterEvents>(event: K, ...args: Parameters<UpdaterEvents[K]>): boolean;
|
|
12
|
+
checkForUpdates(): Promise<UpdateInfo>;
|
|
13
|
+
downloadUpdate(): Promise<string>;
|
|
14
|
+
installUpdate(): Promise<void>;
|
|
15
|
+
startAutoCheck(): void;
|
|
16
|
+
stopAutoCheck(): void;
|
|
17
|
+
getUpdateInfo(): UpdateInfo | null;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=updater.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"updater.d.ts","sourceRoot":"","sources":["../src/updater.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAKtC,OAAO,EAIL,UAAU,EACV,aAAa,EACb,aAAa,EACd,MAAM,SAAS,CAAC;AAEjB,qBAAa,OAAQ,SAAQ,YAAY;IACvC,OAAO,CAAC,MAAM,CAA0B;IACxC,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,UAAU,CAA2B;IAC7C,OAAO,CAAC,cAAc,CAAuB;IAC7C,OAAO,CAAC,UAAU,CAA+B;gBAErC,MAAM,EAAE,aAAa;IAmBjC,EAAE,CAAC,CAAC,SAAS,MAAM,aAAa,EAAE,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,IAAI;IAI7E,IAAI,CAAC,CAAC,SAAS,MAAM,aAAa,EAAE,KAAK,EAAE,CAAC,EAAE,GAAG,IAAI,EAAE,UAAU,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO;IAIvF,eAAe,IAAI,OAAO,CAAC,UAAU,CAAC;IAmCtC,cAAc,IAAI,OAAO,CAAC,MAAM,CAAC;IA4DjC,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;IA6CpC,cAAc,IAAI,IAAI;IAQtB,aAAa,IAAI,IAAI;IAOrB,aAAa,IAAI,UAAU,GAAG,IAAI;CAGnC"}
|
package/dist/updater.js
ADDED
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.Updater = void 0;
|
|
40
|
+
const axios_1 = __importDefault(require("axios"));
|
|
41
|
+
const crypto = __importStar(require("crypto"));
|
|
42
|
+
const electron_1 = require("electron");
|
|
43
|
+
const events_1 = require("events");
|
|
44
|
+
const extract_zip_1 = __importDefault(require("extract-zip"));
|
|
45
|
+
const fs = __importStar(require("fs"));
|
|
46
|
+
const path = __importStar(require("path"));
|
|
47
|
+
const tar = __importStar(require("tar"));
|
|
48
|
+
class Updater extends events_1.EventEmitter {
|
|
49
|
+
constructor(config) {
|
|
50
|
+
super();
|
|
51
|
+
this.updateInfo = null;
|
|
52
|
+
this.downloadedFile = null;
|
|
53
|
+
this.checkTimer = null;
|
|
54
|
+
this.config = {
|
|
55
|
+
channel: 'stable',
|
|
56
|
+
autoDownload: false,
|
|
57
|
+
autoInstall: false,
|
|
58
|
+
checkInterval: 0,
|
|
59
|
+
...config,
|
|
60
|
+
};
|
|
61
|
+
this.client = axios_1.default.create({
|
|
62
|
+
baseURL: this.config.serverUrl,
|
|
63
|
+
headers: {
|
|
64
|
+
'Content-Type': 'application/json',
|
|
65
|
+
},
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
on(event, listener) {
|
|
69
|
+
return super.on(event, listener);
|
|
70
|
+
}
|
|
71
|
+
emit(event, ...args) {
|
|
72
|
+
return super.emit(event, ...args);
|
|
73
|
+
}
|
|
74
|
+
async checkForUpdates() {
|
|
75
|
+
this.emit('checking-for-update');
|
|
76
|
+
try {
|
|
77
|
+
const platform = process.platform;
|
|
78
|
+
const arch = process.arch;
|
|
79
|
+
const response = await this.client.post('/api/update/check', {
|
|
80
|
+
appSlug: this.config.appSlug,
|
|
81
|
+
currentVersion: this.config.currentVersion,
|
|
82
|
+
platform,
|
|
83
|
+
arch,
|
|
84
|
+
channel: this.config.channel,
|
|
85
|
+
});
|
|
86
|
+
this.updateInfo = response.data;
|
|
87
|
+
if (this.updateInfo.updateAvailable) {
|
|
88
|
+
this.emit('update-available', this.updateInfo);
|
|
89
|
+
if (this.config.autoDownload) {
|
|
90
|
+
await this.downloadUpdate();
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
this.emit('update-not-available');
|
|
95
|
+
}
|
|
96
|
+
return this.updateInfo;
|
|
97
|
+
}
|
|
98
|
+
catch (error) {
|
|
99
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
100
|
+
this.emit('error', err);
|
|
101
|
+
throw err;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
async downloadUpdate() {
|
|
105
|
+
if (!this.updateInfo?.downloadUrl) {
|
|
106
|
+
throw new Error('No update available to download');
|
|
107
|
+
}
|
|
108
|
+
const tempDir = electron_1.app.getPath('temp');
|
|
109
|
+
const fileName = this.updateInfo.fileName || `update-${this.updateInfo.version}`;
|
|
110
|
+
const filePath = path.join(tempDir, fileName);
|
|
111
|
+
try {
|
|
112
|
+
const response = await (0, axios_1.default)({
|
|
113
|
+
method: 'GET',
|
|
114
|
+
url: this.updateInfo.downloadUrl,
|
|
115
|
+
responseType: 'stream',
|
|
116
|
+
onDownloadProgress: progressEvent => {
|
|
117
|
+
if (progressEvent.total) {
|
|
118
|
+
const progress = {
|
|
119
|
+
percent: Math.round((progressEvent.loaded / progressEvent.total) * 100),
|
|
120
|
+
transferred: progressEvent.loaded,
|
|
121
|
+
total: progressEvent.total,
|
|
122
|
+
bytesPerSecond: progressEvent.rate || 0,
|
|
123
|
+
};
|
|
124
|
+
this.emit('download-progress', progress);
|
|
125
|
+
}
|
|
126
|
+
},
|
|
127
|
+
});
|
|
128
|
+
const writer = fs.createWriteStream(filePath);
|
|
129
|
+
response.data.pipe(writer);
|
|
130
|
+
await new Promise((resolve, reject) => {
|
|
131
|
+
writer.on('finish', resolve);
|
|
132
|
+
writer.on('error', reject);
|
|
133
|
+
});
|
|
134
|
+
if (this.updateInfo.checksum) {
|
|
135
|
+
const fileBuffer = fs.readFileSync(filePath);
|
|
136
|
+
const hash = crypto.createHash('sha256').update(fileBuffer).digest('hex');
|
|
137
|
+
if (hash !== this.updateInfo.checksum) {
|
|
138
|
+
fs.unlinkSync(filePath);
|
|
139
|
+
throw new Error('Checksum verification failed');
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
this.downloadedFile = filePath;
|
|
143
|
+
this.emit('update-downloaded', this.updateInfo);
|
|
144
|
+
if (this.config.autoInstall) {
|
|
145
|
+
await this.installUpdate();
|
|
146
|
+
}
|
|
147
|
+
return filePath;
|
|
148
|
+
}
|
|
149
|
+
catch (error) {
|
|
150
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
151
|
+
this.emit('error', err);
|
|
152
|
+
throw err;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
async installUpdate() {
|
|
156
|
+
if (!this.downloadedFile || !this.updateInfo) {
|
|
157
|
+
throw new Error('No update downloaded');
|
|
158
|
+
}
|
|
159
|
+
const appPath = electron_1.app.getAppPath();
|
|
160
|
+
const updateDir = path.dirname(appPath);
|
|
161
|
+
const backupDir = path.join(updateDir, '.backup');
|
|
162
|
+
try {
|
|
163
|
+
if (fs.existsSync(backupDir)) {
|
|
164
|
+
fs.rmSync(backupDir, { recursive: true });
|
|
165
|
+
}
|
|
166
|
+
fs.mkdirSync(backupDir, { recursive: true });
|
|
167
|
+
const ext = path.extname(this.downloadedFile).toLowerCase();
|
|
168
|
+
if (ext === '.zip') {
|
|
169
|
+
await (0, extract_zip_1.default)(this.downloadedFile, { dir: updateDir });
|
|
170
|
+
}
|
|
171
|
+
else if (ext === '.gz' || this.downloadedFile.endsWith('.tar.gz')) {
|
|
172
|
+
await tar.extract({
|
|
173
|
+
file: this.downloadedFile,
|
|
174
|
+
cwd: updateDir,
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
else if (ext === '.appimage' || ext === '.exe') {
|
|
178
|
+
const targetPath = path.join(updateDir, path.basename(this.downloadedFile));
|
|
179
|
+
fs.copyFileSync(this.downloadedFile, targetPath);
|
|
180
|
+
if (ext === '.appimage') {
|
|
181
|
+
fs.chmodSync(targetPath, 0o755);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
fs.unlinkSync(this.downloadedFile);
|
|
185
|
+
this.downloadedFile = null;
|
|
186
|
+
electron_1.app.relaunch();
|
|
187
|
+
electron_1.app.exit(0);
|
|
188
|
+
}
|
|
189
|
+
catch (error) {
|
|
190
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
191
|
+
this.emit('error', err);
|
|
192
|
+
throw err;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
startAutoCheck() {
|
|
196
|
+
if (this.config.checkInterval > 0) {
|
|
197
|
+
this.checkTimer = setInterval(() => {
|
|
198
|
+
this.checkForUpdates().catch(() => { });
|
|
199
|
+
}, this.config.checkInterval);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
stopAutoCheck() {
|
|
203
|
+
if (this.checkTimer) {
|
|
204
|
+
clearInterval(this.checkTimer);
|
|
205
|
+
this.checkTimer = null;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
getUpdateInfo() {
|
|
209
|
+
return this.updateInfo;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
exports.Updater = Updater;
|
|
213
|
+
//# sourceMappingURL=updater.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"updater.js","sourceRoot":"","sources":["../src/updater.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@alphamatica/app-updater",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Electron auto-updater client for A-Updater service",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"module": "dist/index.mjs",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"require": "./dist/index.js",
|
|
12
|
+
"import": "./dist/index.mjs"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist",
|
|
17
|
+
"README.md",
|
|
18
|
+
"CHANGELOG.md",
|
|
19
|
+
"LICENSE"
|
|
20
|
+
],
|
|
21
|
+
"scripts": {
|
|
22
|
+
"build": "tsc",
|
|
23
|
+
"dev": "tsc --watch",
|
|
24
|
+
"clean": "rimraf dist",
|
|
25
|
+
"prepublishOnly": "yarn clean && yarn build"
|
|
26
|
+
},
|
|
27
|
+
"keywords": [
|
|
28
|
+
"electron",
|
|
29
|
+
"updater",
|
|
30
|
+
"auto-update",
|
|
31
|
+
"electron-updater",
|
|
32
|
+
"update",
|
|
33
|
+
"a-updater"
|
|
34
|
+
],
|
|
35
|
+
"author": "Alphamatica",
|
|
36
|
+
"license": "MIT",
|
|
37
|
+
"engines": {
|
|
38
|
+
"node": ">=16.0.0"
|
|
39
|
+
},
|
|
40
|
+
"dependencies": {
|
|
41
|
+
"axios": "^1.6.5",
|
|
42
|
+
"extract-zip": "^2.0.1",
|
|
43
|
+
"tar": "^6.2.0"
|
|
44
|
+
},
|
|
45
|
+
"devDependencies": {
|
|
46
|
+
"@types/node": "^20.11.0",
|
|
47
|
+
"@types/tar": "^6.1.10",
|
|
48
|
+
"electron": "^28.1.0",
|
|
49
|
+
"rimraf": "^5.0.5",
|
|
50
|
+
"typescript": "^5.3.3"
|
|
51
|
+
},
|
|
52
|
+
"peerDependencies": {
|
|
53
|
+
"electron": ">=20.0.0"
|
|
54
|
+
}
|
|
55
|
+
}
|