UNPKG

7.72 kBJavaScriptView Raw
1"use strict";
2
3Object.defineProperty(exports, "__esModule", {
4 value: true
5});
6exports.createTempUpdateFile = createTempUpdateFile;
7exports.DownloadedUpdateHelper = void 0;
8
9function _crypto() {
10 const data = require("crypto");
11
12 _crypto = function () {
13 return data;
14 };
15
16 return data;
17}
18
19var _fs = require("fs");
20
21function _lodash() {
22 const data = _interopRequireDefault(require("lodash.isequal"));
23
24 _lodash = function () {
25 return data;
26 };
27
28 return data;
29}
30
31function _fsExtra() {
32 const data = require("fs-extra");
33
34 _fsExtra = function () {
35 return data;
36 };
37
38 return data;
39}
40
41var path = _interopRequireWildcard(require("path"));
42
43function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }
44
45function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
46
47function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
48
49/** @private **/
50class DownloadedUpdateHelper {
51 constructor(cacheDir) {
52 this.cacheDir = cacheDir;
53 this._file = null;
54 this._packageFile = null;
55 this.versionInfo = null;
56 this.fileInfo = null;
57 this._downloadedFileInfo = null;
58 }
59
60 get downloadedFileInfo() {
61 return this._downloadedFileInfo;
62 }
63
64 get file() {
65 return this._file;
66 }
67
68 get packageFile() {
69 return this._packageFile;
70 }
71
72 get cacheDirForPendingUpdate() {
73 return path.join(this.cacheDir, "pending");
74 }
75
76 async validateDownloadedPath(updateFile, updateInfo, fileInfo, logger) {
77 if (this.versionInfo != null && this.file === updateFile && this.fileInfo != null) {
78 // update has already been downloaded from this running instance
79 // check here only existence, not checksum
80 if ((0, _lodash().default)(this.versionInfo, updateInfo) && (0, _lodash().default)(this.fileInfo.info, fileInfo.info) && (await (0, _fsExtra().pathExists)(updateFile))) {
81 return updateFile;
82 } else {
83 return null;
84 }
85 } // update has already been downloaded from some previous app launch
86
87
88 const cachedUpdateFile = await this.getValidCachedUpdateFile(fileInfo, logger);
89
90 if (cachedUpdateFile === null) {
91 return null;
92 }
93
94 logger.info(`Update has already been downloaded to ${updateFile}).`);
95 this._file = cachedUpdateFile;
96 return cachedUpdateFile;
97 }
98
99 async setDownloadedFile(downloadedFile, packageFile, versionInfo, fileInfo, updateFileName, isSaveCache) {
100 this._file = downloadedFile;
101 this._packageFile = packageFile;
102 this.versionInfo = versionInfo;
103 this.fileInfo = fileInfo;
104 this._downloadedFileInfo = {
105 fileName: updateFileName,
106 sha512: fileInfo.info.sha512,
107 isAdminRightsRequired: fileInfo.info.isAdminRightsRequired === true
108 };
109
110 if (isSaveCache) {
111 await (0, _fsExtra().outputJson)(this.getUpdateInfoFile(), this._downloadedFileInfo);
112 }
113 }
114
115 async clear() {
116 this._file = null;
117 this._packageFile = null;
118 this.versionInfo = null;
119 this.fileInfo = null;
120 await this.cleanCacheDirForPendingUpdate();
121 }
122
123 async cleanCacheDirForPendingUpdate() {
124 try {
125 // remove stale data
126 await (0, _fsExtra().emptyDir)(this.cacheDirForPendingUpdate);
127 } catch (ignore) {// ignore
128 }
129 }
130 /**
131 * Returns "update-info.json" which is created in the update cache directory's "pending" subfolder after the first update is downloaded. If the update file does not exist then the cache is cleared and recreated. If the update file exists then its properties are validated.
132 * @param fileInfo
133 * @param logger
134 */
135
136
137 async getValidCachedUpdateFile(fileInfo, logger) {
138 var _a;
139
140 const updateInfoFilePath = this.getUpdateInfoFile();
141 const doesUpdateInfoFileExist = await (0, _fsExtra().pathExistsSync)(updateInfoFilePath);
142
143 if (!doesUpdateInfoFileExist) {
144 return null;
145 }
146
147 let cachedInfo;
148
149 try {
150 cachedInfo = await (0, _fsExtra().readJson)(updateInfoFilePath);
151 } catch (error) {
152 let message = `No cached update info available`;
153
154 if (error.code !== "ENOENT") {
155 await this.cleanCacheDirForPendingUpdate();
156 message += ` (error on read: ${error.message})`;
157 }
158
159 logger.info(message);
160 return null;
161 }
162
163 const isCachedInfoFileNameValid = (_a = (cachedInfo === null || cachedInfo === void 0 ? void 0 : cachedInfo.fileName) !== null) !== null && _a !== void 0 ? _a : false;
164
165 if (!isCachedInfoFileNameValid) {
166 logger.warn(`Cached update info is corrupted: no fileName, directory for cached update will be cleaned`);
167 await this.cleanCacheDirForPendingUpdate();
168 return null;
169 }
170
171 if (fileInfo.info.sha512 !== cachedInfo.sha512) {
172 logger.info(`Cached update sha512 checksum doesn't match the latest available update. New update must be downloaded. Cached: ${cachedInfo.sha512}, expected: ${fileInfo.info.sha512}. Directory for cached update will be cleaned`);
173 await this.cleanCacheDirForPendingUpdate();
174 return null;
175 }
176
177 const updateFile = path.join(this.cacheDirForPendingUpdate, cachedInfo.fileName);
178
179 if (!(await (0, _fsExtra().pathExists)(updateFile))) {
180 logger.info("Cached update file doesn't exist");
181 return null;
182 }
183
184 const sha512 = await hashFile(updateFile);
185
186 if (fileInfo.info.sha512 !== sha512) {
187 logger.warn(`Sha512 checksum doesn't match the latest available update. New update must be downloaded. Cached: ${sha512}, expected: ${fileInfo.info.sha512}`);
188 await this.cleanCacheDirForPendingUpdate();
189 return null;
190 }
191
192 this._downloadedFileInfo = cachedInfo;
193 return updateFile;
194 }
195
196 getUpdateInfoFile() {
197 return path.join(this.cacheDirForPendingUpdate, "update-info.json");
198 }
199
200}
201
202exports.DownloadedUpdateHelper = DownloadedUpdateHelper;
203
204function hashFile(file, algorithm = "sha512", encoding = "base64", options) {
205 return new Promise((resolve, reject) => {
206 const hash = (0, _crypto().createHash)(algorithm);
207 hash.on("error", reject).setEncoding(encoding);
208 (0, _fs.createReadStream)(file, { ...options,
209 highWaterMark: 1024 * 1024
210 /* better to use more memory but hash faster */
211
212 }).on("error", reject).on("end", () => {
213 hash.end();
214 resolve(hash.read());
215 }).pipe(hash, {
216 end: false
217 });
218 });
219}
220
221async function createTempUpdateFile(name, cacheDir, log) {
222 // https://github.com/electron-userland/electron-builder/pull/2474#issuecomment-366481912
223 let nameCounter = 0;
224 let result = path.join(cacheDir, name);
225
226 for (let i = 0; i < 3; i++) {
227 try {
228 await (0, _fsExtra().unlink)(result);
229 return result;
230 } catch (e) {
231 if (e.code === "ENOENT") {
232 return result;
233 }
234
235 log.warn(`Error on remove temp update file: ${e}`);
236 result = path.join(cacheDir, `${nameCounter++}-${name}`);
237 }
238 }
239
240 return result;
241}
242// __ts-babel@6.0.4
243//# sourceMappingURL=DownloadedUpdateHelper.js.map
\No newline at end of file