electron-version-deployer-cli 0.0.1

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.
@@ -0,0 +1,306 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const electron = require("electron");
4
+ const node_url = require("node:url");
5
+ const node_path = require("node:path");
6
+ const node_https = require("node:https");
7
+ const node_fs = require("node:fs");
8
+ const extract = require("extract-zip");
9
+ function fetchRemoteChangelogJSON(remote_url) {
10
+ return new Promise((res, rej) => {
11
+ node_https.get(`${remote_url}/changelog.json`, (_res) => {
12
+ let data = "";
13
+ _res.on("data", (chunk) => {
14
+ data += chunk;
15
+ });
16
+ _res.on("end", () => {
17
+ try {
18
+ res(JSON.parse(data));
19
+ } catch (e) {
20
+ res(null);
21
+ }
22
+ });
23
+ }).on("error", (err) => {
24
+ rej(`获取 changelog.json 失败:` + err.toString());
25
+ });
26
+ });
27
+ }
28
+ function fetchRemotePkgJSON(remote_url) {
29
+ return new Promise((res, rej) => {
30
+ node_https.get(`${remote_url}/package.json`, (_res) => {
31
+ let data = "";
32
+ _res.on("data", (chunk) => {
33
+ data += chunk;
34
+ });
35
+ _res.on("end", () => {
36
+ try {
37
+ res(JSON.parse(data));
38
+ } catch (e) {
39
+ res(null);
40
+ }
41
+ });
42
+ }).on("error", (err) => {
43
+ rej(`自动更新检查请求失败:` + err.toString());
44
+ });
45
+ });
46
+ }
47
+ function versionToNum(a) {
48
+ let c = a.split(".");
49
+ let num_place = ["", "0", "00", "000", "0000"], r = num_place.reverse();
50
+ for (let i = 0; i < c.length; i++) {
51
+ let len = c[i].length;
52
+ c[i] = r[len] + c[i];
53
+ }
54
+ let res = c.join("");
55
+ return res;
56
+ }
57
+ function compareObjectsIsEqual(obj1, obj2) {
58
+ const keys1 = Object.keys(obj1);
59
+ const keys2 = Object.keys(obj2);
60
+ if (keys1.length !== keys2.length) {
61
+ return false;
62
+ }
63
+ for (let key of keys1) {
64
+ if (obj1[key] !== obj2[key]) {
65
+ return false;
66
+ }
67
+ }
68
+ return true;
69
+ }
70
+ const CLI_NAME = "electron-version-deployer-cli";
71
+ const id = `${Date.now()}-${Math.random()}`;
72
+ var EVDEventEnum = /* @__PURE__ */ ((EVDEventEnum2) => {
73
+ EVDEventEnum2["OPEN_LINK"] = "evd-open-link";
74
+ EVDEventEnum2["UPDATE"] = "evd-update-now";
75
+ EVDEventEnum2["SKIP"] = "evd-skip";
76
+ EVDEventEnum2["GET_CHANGELOGS"] = "evd-get-change-logs";
77
+ return EVDEventEnum2;
78
+ })(EVDEventEnum || {});
79
+ let globalArgs = null;
80
+ let cacheCurrentPkgJSON = null;
81
+ function EVDInit(props) {
82
+ globalArgs = props;
83
+ const { detectionFrequency, detectAtStart, onError } = getConfigs();
84
+ setInterval(async () => {
85
+ try {
86
+ await EVDCheckUpdate();
87
+ } catch (e) {
88
+ onError(e);
89
+ }
90
+ }, 1e3 * detectionFrequency);
91
+ if (!detectAtStart)
92
+ return;
93
+ setTimeout(async () => {
94
+ try {
95
+ await EVDCheckUpdate();
96
+ } catch (e) {
97
+ onError(e);
98
+ }
99
+ }, 1e3 * 2);
100
+ const appPath = electron.app.getAppPath();
101
+ cacheCurrentPkgJSON = JSON.parse(
102
+ node_fs.readFileSync(node_path.join(appPath, "package.json"), "utf-8")
103
+ );
104
+ }
105
+ async function EVDCheckUpdate() {
106
+ const { netlifyUrl } = getConfigs();
107
+ const { version } = cacheCurrentPkgJSON;
108
+ const remoteJSON = await fetchRemotePkgJSON(netlifyUrl);
109
+ if (!remoteJSON)
110
+ throw new Error(`${netlifyUrl}package.json 文件不存在`);
111
+ const localVersion = versionToNum(version);
112
+ const remoteVersion = versionToNum(remoteJSON.version);
113
+ if (remoteVersion > localVersion) {
114
+ await showNewVersionDialog();
115
+ }
116
+ }
117
+ async function showNewVersionDialog() {
118
+ const { windowHeight, windowWidth, onError } = getConfigs();
119
+ electron.app.whenReady().then(async () => {
120
+ try {
121
+ let promptWindow = new electron.BrowserWindow({
122
+ frame: true,
123
+ width: windowWidth,
124
+ height: windowHeight,
125
+ minWidth: windowWidth,
126
+ minHeight: windowHeight,
127
+ resizable: false,
128
+ minimizable: true,
129
+ fullscreenable: false,
130
+ maximizable: false,
131
+ skipTaskbar: true,
132
+ alwaysOnTop: true,
133
+ useContentSize: false,
134
+ title: "有可用的更新",
135
+ webPreferences: {
136
+ nodeIntegration: true,
137
+ contextIsolation: false
138
+ },
139
+ show: false
140
+ });
141
+ promptWindow.setMenu(null);
142
+ promptWindow.setMenuBarVisibility(false);
143
+ const promptUrl = node_url.format({
144
+ protocol: "file",
145
+ slashes: true,
146
+ pathname: node_path.join(
147
+ electron.app.getAppPath(),
148
+ "node_modules",
149
+ CLI_NAME,
150
+ "dist",
151
+ "templates",
152
+ "newVersionDialog.html"
153
+ ),
154
+ hash: id
155
+ });
156
+ promptWindow.loadURL(promptUrl);
157
+ promptWindow.once("ready-to-show", () => {
158
+ promptWindow.show();
159
+ });
160
+ promptWindow.once("close", () => {
161
+ cleanup(promptWindow);
162
+ });
163
+ bindEvent(promptWindow);
164
+ } catch (e) {
165
+ onError(e);
166
+ }
167
+ });
168
+ }
169
+ async function installNewVersion() {
170
+ const { netlifyUrl } = getConfigs();
171
+ const remoteJSON = await fetchRemotePkgJSON(netlifyUrl);
172
+ const needInstallFullSize = compareObjectsIsEqual(
173
+ remoteJSON.dependencies,
174
+ cacheCurrentPkgJSON.dependencies
175
+ );
176
+ try {
177
+ await installPkg(needInstallFullSize ? "fullCode.zip" : "logicCode.zip");
178
+ } catch (error) {
179
+ node_fs.appendFileSync(
180
+ node_path.join(electron.app.getPath("userData"), "evd-runtime-error.txt"),
181
+ `
182
+ ${(/* @__PURE__ */ new Date()).toString()}
183
+
184
+ ${error.toString()}
185
+
186
+ -- stack
187
+
188
+ ${error.stack}
189
+
190
+ ----------------------------------------------------------------
191
+
192
+ `
193
+ );
194
+ }
195
+ }
196
+ async function installPkg(zipFile) {
197
+ const { netlifyUrl } = getConfigs();
198
+ const appPath = electron.app.getAppPath();
199
+ const unzipPath = node_path.join(appPath, "evdUnzip");
200
+ if (node_fs.existsSync(unzipPath)) {
201
+ node_fs.rmSync(unzipPath, {
202
+ force: true,
203
+ maxRetries: 3,
204
+ recursive: true
205
+ });
206
+ }
207
+ node_fs.mkdirSync(unzipPath);
208
+ const tmpZipFilePath = node_fs.createWriteStream(unzipPath + ".zip");
209
+ await new Promise(
210
+ (res, rej) => node_https.get(`${netlifyUrl}/${zipFile}`, (response) => {
211
+ response.pipe(tmpZipFilePath).on("finish", () => {
212
+ res();
213
+ }).on("error", (err) => {
214
+ rej(err);
215
+ });
216
+ }).on("error", (err) => {
217
+ rej(err);
218
+ })
219
+ );
220
+ await extract(unzipPath + ".zip", { dir: unzipPath });
221
+ await new Promise((res) => setTimeout(res, 1e3));
222
+ copyFolderRecursiveSync(unzipPath, appPath);
223
+ await new Promise((res) => setTimeout(res, 1e3));
224
+ }
225
+ function bindEvent(promptWindow) {
226
+ electron.ipcMain.on("evd-open-link", (_, link) => {
227
+ electron.shell.openExternal(link);
228
+ });
229
+ electron.ipcMain.on("evd-skip", (_) => {
230
+ promptWindow.close();
231
+ });
232
+ electron.ipcMain.on("evd-update-now", (_) => {
233
+ installNewVersion().then(() => {
234
+ console.log(222);
235
+ promptWindow.close();
236
+ electron.app.relaunch();
237
+ electron.app.exit();
238
+ });
239
+ });
240
+ electron.ipcMain.handle("evd-get-change-logs", async () => {
241
+ const { netlifyUrl } = getConfigs();
242
+ return await fetchRemoteChangelogJSON(netlifyUrl);
243
+ });
244
+ }
245
+ function cleanup(promptWindow) {
246
+ electron.ipcMain.removeAllListeners(
247
+ "evd-open-link"
248
+ /* OPEN_LINK */
249
+ );
250
+ electron.ipcMain.removeAllListeners(
251
+ "evd-skip"
252
+ /* SKIP */
253
+ );
254
+ electron.ipcMain.removeAllListeners(
255
+ "evd-update-now"
256
+ /* UPDATE */
257
+ );
258
+ promptWindow == null ? void 0 : promptWindow.focus();
259
+ if (promptWindow) {
260
+ promptWindow.destroy();
261
+ }
262
+ }
263
+ function getConfigs() {
264
+ if (!globalArgs)
265
+ throw new Error("必须先执行 EVDInit 后才能继续运行!");
266
+ return {
267
+ ...{
268
+ onError: () => {
269
+ },
270
+ windowHeight: 360,
271
+ windowWidth: 400,
272
+ logo: void 0,
273
+ // 默认六小时检测一次
274
+ detectionFrequency: 60 * 60 * 6,
275
+ detectAtStart: true
276
+ },
277
+ ...globalArgs
278
+ };
279
+ }
280
+ function copyFileSync(source, target) {
281
+ let targetFile = target;
282
+ if (node_fs.existsSync(target)) {
283
+ if (node_fs.statSync(target).isDirectory()) {
284
+ targetFile = node_path.join(target, node_path.basename(source));
285
+ }
286
+ }
287
+ node_fs.writeFileSync(targetFile, node_fs.readFileSync(source));
288
+ }
289
+ function copyFolderRecursiveSync(source, target) {
290
+ if (!node_fs.existsSync(target)) {
291
+ node_fs.mkdirSync(target);
292
+ }
293
+ const files = node_fs.readdirSync(source);
294
+ files.forEach((file) => {
295
+ const sourcePath = node_path.join(source, file);
296
+ const targetPath = node_path.join(target, file);
297
+ if (node_fs.statSync(sourcePath).isDirectory()) {
298
+ copyFolderRecursiveSync(sourcePath, targetPath);
299
+ } else {
300
+ copyFileSync(sourcePath, targetPath);
301
+ }
302
+ });
303
+ }
304
+ exports.EVDCheckUpdate = EVDCheckUpdate;
305
+ exports.EVDEventEnum = EVDEventEnum;
306
+ exports.EVDInit = EVDInit;
package/dist/main.d.ts ADDED
@@ -0,0 +1,18 @@
1
+ export declare enum EVDEventEnum {
2
+ OPEN_LINK = "evd-open-link",
3
+ UPDATE = "evd-update-now",
4
+ SKIP = "evd-skip",
5
+ GET_CHANGELOGS = "evd-get-change-logs"
6
+ }
7
+ type EVDInitPropsType = {
8
+ netlifyUrl: string;
9
+ windowWidth?: number;
10
+ windowHeight?: number;
11
+ logo?: string;
12
+ detectionFrequency?: number;
13
+ detectAtStart?: number;
14
+ onError?: (err: unknown) => void;
15
+ };
16
+ export declare function EVDInit(props: EVDInitPropsType): void;
17
+ export declare function EVDCheckUpdate(): Promise<void>;
18
+ export {};
@@ -0,0 +1,306 @@
1
+ import { app, BrowserWindow, ipcMain, shell } from "electron";
2
+ import { format } from "node:url";
3
+ import { join, basename } from "node:path";
4
+ import { get } from "node:https";
5
+ import { readFileSync, appendFileSync, existsSync, rmSync, mkdirSync, createWriteStream, readdirSync, statSync, writeFileSync } from "node:fs";
6
+ import extract from "extract-zip";
7
+ function fetchRemoteChangelogJSON(remote_url) {
8
+ return new Promise((res, rej) => {
9
+ get(`${remote_url}/changelog.json`, (_res) => {
10
+ let data = "";
11
+ _res.on("data", (chunk) => {
12
+ data += chunk;
13
+ });
14
+ _res.on("end", () => {
15
+ try {
16
+ res(JSON.parse(data));
17
+ } catch (e) {
18
+ res(null);
19
+ }
20
+ });
21
+ }).on("error", (err) => {
22
+ rej(`获取 changelog.json 失败:` + err.toString());
23
+ });
24
+ });
25
+ }
26
+ function fetchRemotePkgJSON(remote_url) {
27
+ return new Promise((res, rej) => {
28
+ get(`${remote_url}/package.json`, (_res) => {
29
+ let data = "";
30
+ _res.on("data", (chunk) => {
31
+ data += chunk;
32
+ });
33
+ _res.on("end", () => {
34
+ try {
35
+ res(JSON.parse(data));
36
+ } catch (e) {
37
+ res(null);
38
+ }
39
+ });
40
+ }).on("error", (err) => {
41
+ rej(`自动更新检查请求失败:` + err.toString());
42
+ });
43
+ });
44
+ }
45
+ function versionToNum(a) {
46
+ let c = a.split(".");
47
+ let num_place = ["", "0", "00", "000", "0000"], r = num_place.reverse();
48
+ for (let i = 0; i < c.length; i++) {
49
+ let len = c[i].length;
50
+ c[i] = r[len] + c[i];
51
+ }
52
+ let res = c.join("");
53
+ return res;
54
+ }
55
+ function compareObjectsIsEqual(obj1, obj2) {
56
+ const keys1 = Object.keys(obj1);
57
+ const keys2 = Object.keys(obj2);
58
+ if (keys1.length !== keys2.length) {
59
+ return false;
60
+ }
61
+ for (let key of keys1) {
62
+ if (obj1[key] !== obj2[key]) {
63
+ return false;
64
+ }
65
+ }
66
+ return true;
67
+ }
68
+ const CLI_NAME = "electron-version-deployer-cli";
69
+ const id = `${Date.now()}-${Math.random()}`;
70
+ var EVDEventEnum = /* @__PURE__ */ ((EVDEventEnum2) => {
71
+ EVDEventEnum2["OPEN_LINK"] = "evd-open-link";
72
+ EVDEventEnum2["UPDATE"] = "evd-update-now";
73
+ EVDEventEnum2["SKIP"] = "evd-skip";
74
+ EVDEventEnum2["GET_CHANGELOGS"] = "evd-get-change-logs";
75
+ return EVDEventEnum2;
76
+ })(EVDEventEnum || {});
77
+ let globalArgs = null;
78
+ let cacheCurrentPkgJSON = null;
79
+ function EVDInit(props) {
80
+ globalArgs = props;
81
+ const { detectionFrequency, detectAtStart, onError } = getConfigs();
82
+ setInterval(async () => {
83
+ try {
84
+ await EVDCheckUpdate();
85
+ } catch (e) {
86
+ onError(e);
87
+ }
88
+ }, 1e3 * detectionFrequency);
89
+ if (!detectAtStart)
90
+ return;
91
+ setTimeout(async () => {
92
+ try {
93
+ await EVDCheckUpdate();
94
+ } catch (e) {
95
+ onError(e);
96
+ }
97
+ }, 1e3 * 2);
98
+ const appPath = app.getAppPath();
99
+ cacheCurrentPkgJSON = JSON.parse(
100
+ readFileSync(join(appPath, "package.json"), "utf-8")
101
+ );
102
+ }
103
+ async function EVDCheckUpdate() {
104
+ const { netlifyUrl } = getConfigs();
105
+ const { version } = cacheCurrentPkgJSON;
106
+ const remoteJSON = await fetchRemotePkgJSON(netlifyUrl);
107
+ if (!remoteJSON)
108
+ throw new Error(`${netlifyUrl}package.json 文件不存在`);
109
+ const localVersion = versionToNum(version);
110
+ const remoteVersion = versionToNum(remoteJSON.version);
111
+ if (remoteVersion > localVersion) {
112
+ await showNewVersionDialog();
113
+ }
114
+ }
115
+ async function showNewVersionDialog() {
116
+ const { windowHeight, windowWidth, onError } = getConfigs();
117
+ app.whenReady().then(async () => {
118
+ try {
119
+ let promptWindow = new BrowserWindow({
120
+ frame: true,
121
+ width: windowWidth,
122
+ height: windowHeight,
123
+ minWidth: windowWidth,
124
+ minHeight: windowHeight,
125
+ resizable: false,
126
+ minimizable: true,
127
+ fullscreenable: false,
128
+ maximizable: false,
129
+ skipTaskbar: true,
130
+ alwaysOnTop: true,
131
+ useContentSize: false,
132
+ title: "有可用的更新",
133
+ webPreferences: {
134
+ nodeIntegration: true,
135
+ contextIsolation: false
136
+ },
137
+ show: false
138
+ });
139
+ promptWindow.setMenu(null);
140
+ promptWindow.setMenuBarVisibility(false);
141
+ const promptUrl = format({
142
+ protocol: "file",
143
+ slashes: true,
144
+ pathname: join(
145
+ app.getAppPath(),
146
+ "node_modules",
147
+ CLI_NAME,
148
+ "dist",
149
+ "templates",
150
+ "newVersionDialog.html"
151
+ ),
152
+ hash: id
153
+ });
154
+ promptWindow.loadURL(promptUrl);
155
+ promptWindow.once("ready-to-show", () => {
156
+ promptWindow.show();
157
+ });
158
+ promptWindow.once("close", () => {
159
+ cleanup(promptWindow);
160
+ });
161
+ bindEvent(promptWindow);
162
+ } catch (e) {
163
+ onError(e);
164
+ }
165
+ });
166
+ }
167
+ async function installNewVersion() {
168
+ const { netlifyUrl } = getConfigs();
169
+ const remoteJSON = await fetchRemotePkgJSON(netlifyUrl);
170
+ const needInstallFullSize = compareObjectsIsEqual(
171
+ remoteJSON.dependencies,
172
+ cacheCurrentPkgJSON.dependencies
173
+ );
174
+ try {
175
+ await installPkg(needInstallFullSize ? "fullCode.zip" : "logicCode.zip");
176
+ } catch (error) {
177
+ appendFileSync(
178
+ join(app.getPath("userData"), "evd-runtime-error.txt"),
179
+ `
180
+ ${(/* @__PURE__ */ new Date()).toString()}
181
+
182
+ ${error.toString()}
183
+
184
+ -- stack
185
+
186
+ ${error.stack}
187
+
188
+ ----------------------------------------------------------------
189
+
190
+ `
191
+ );
192
+ }
193
+ }
194
+ async function installPkg(zipFile) {
195
+ const { netlifyUrl } = getConfigs();
196
+ const appPath = app.getAppPath();
197
+ const unzipPath = join(appPath, "evdUnzip");
198
+ if (existsSync(unzipPath)) {
199
+ rmSync(unzipPath, {
200
+ force: true,
201
+ maxRetries: 3,
202
+ recursive: true
203
+ });
204
+ }
205
+ mkdirSync(unzipPath);
206
+ const tmpZipFilePath = createWriteStream(unzipPath + ".zip");
207
+ await new Promise(
208
+ (res, rej) => get(`${netlifyUrl}/${zipFile}`, (response) => {
209
+ response.pipe(tmpZipFilePath).on("finish", () => {
210
+ res();
211
+ }).on("error", (err) => {
212
+ rej(err);
213
+ });
214
+ }).on("error", (err) => {
215
+ rej(err);
216
+ })
217
+ );
218
+ await extract(unzipPath + ".zip", { dir: unzipPath });
219
+ await new Promise((res) => setTimeout(res, 1e3));
220
+ copyFolderRecursiveSync(unzipPath, appPath);
221
+ await new Promise((res) => setTimeout(res, 1e3));
222
+ }
223
+ function bindEvent(promptWindow) {
224
+ ipcMain.on("evd-open-link", (_, link) => {
225
+ shell.openExternal(link);
226
+ });
227
+ ipcMain.on("evd-skip", (_) => {
228
+ promptWindow.close();
229
+ });
230
+ ipcMain.on("evd-update-now", (_) => {
231
+ installNewVersion().then(() => {
232
+ console.log(222);
233
+ promptWindow.close();
234
+ app.relaunch();
235
+ app.exit();
236
+ });
237
+ });
238
+ ipcMain.handle("evd-get-change-logs", async () => {
239
+ const { netlifyUrl } = getConfigs();
240
+ return await fetchRemoteChangelogJSON(netlifyUrl);
241
+ });
242
+ }
243
+ function cleanup(promptWindow) {
244
+ ipcMain.removeAllListeners(
245
+ "evd-open-link"
246
+ /* OPEN_LINK */
247
+ );
248
+ ipcMain.removeAllListeners(
249
+ "evd-skip"
250
+ /* SKIP */
251
+ );
252
+ ipcMain.removeAllListeners(
253
+ "evd-update-now"
254
+ /* UPDATE */
255
+ );
256
+ promptWindow == null ? void 0 : promptWindow.focus();
257
+ if (promptWindow) {
258
+ promptWindow.destroy();
259
+ }
260
+ }
261
+ function getConfigs() {
262
+ if (!globalArgs)
263
+ throw new Error("必须先执行 EVDInit 后才能继续运行!");
264
+ return {
265
+ ...{
266
+ onError: () => {
267
+ },
268
+ windowHeight: 360,
269
+ windowWidth: 400,
270
+ logo: void 0,
271
+ // 默认六小时检测一次
272
+ detectionFrequency: 60 * 60 * 6,
273
+ detectAtStart: true
274
+ },
275
+ ...globalArgs
276
+ };
277
+ }
278
+ function copyFileSync(source, target) {
279
+ let targetFile = target;
280
+ if (existsSync(target)) {
281
+ if (statSync(target).isDirectory()) {
282
+ targetFile = join(target, basename(source));
283
+ }
284
+ }
285
+ writeFileSync(targetFile, readFileSync(source));
286
+ }
287
+ function copyFolderRecursiveSync(source, target) {
288
+ if (!existsSync(target)) {
289
+ mkdirSync(target);
290
+ }
291
+ const files = readdirSync(source);
292
+ files.forEach((file) => {
293
+ const sourcePath = join(source, file);
294
+ const targetPath = join(target, file);
295
+ if (statSync(sourcePath).isDirectory()) {
296
+ copyFolderRecursiveSync(sourcePath, targetPath);
297
+ } else {
298
+ copyFileSync(sourcePath, targetPath);
299
+ }
300
+ });
301
+ }
302
+ export {
303
+ EVDCheckUpdate,
304
+ EVDEventEnum,
305
+ EVDInit
306
+ };
@@ -0,0 +1,19 @@
1
+ // @ts-nocheck
2
+ import { defineEVDConfig } from "@/index";
3
+
4
+ export default defineEVDConfig({
5
+ compileCommand: __compileCommand__,
6
+ changelogsPath: __changelogsPath__,
7
+ sources: {
8
+ folder: __sources_folder__,
9
+ nodeModules: __sources_nodeModules__,
10
+ codes: __sources_codes__,
11
+ packageJSON: __sources_packageJSON__,
12
+ },
13
+ netlify: {
14
+ url: __netlify_url__,
15
+ token: __netlify_token__,
16
+ siteID: __netlify_siteID__,
17
+ },
18
+ prebuiltConfig: {},
19
+ });