UNPKG

7.82 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, directory for cached update will be cleaned");
181 await this.cleanCacheDirForPendingUpdate();
182 return null;
183 }
184
185 const sha512 = await hashFile(updateFile);
186
187 if (fileInfo.info.sha512 !== sha512) {
188 logger.warn(`Sha512 checksum doesn't match the latest available update. New update must be downloaded. Cached: ${sha512}, expected: ${fileInfo.info.sha512}`);
189 await this.cleanCacheDirForPendingUpdate();
190 return null;
191 }
192
193 this._downloadedFileInfo = cachedInfo;
194 return updateFile;
195 }
196
197 getUpdateInfoFile() {
198 return path.join(this.cacheDirForPendingUpdate, "update-info.json");
199 }
200
201}
202
203exports.DownloadedUpdateHelper = DownloadedUpdateHelper;
204
205function hashFile(file, algorithm = "sha512", encoding = "base64", options) {
206 return new Promise((resolve, reject) => {
207 const hash = (0, _crypto().createHash)(algorithm);
208 hash.on("error", reject).setEncoding(encoding);
209 (0, _fs.createReadStream)(file, { ...options,
210 highWaterMark: 1024 * 1024
211 /* better to use more memory but hash faster */
212
213 }).on("error", reject).on("end", () => {
214 hash.end();
215 resolve(hash.read());
216 }).pipe(hash, {
217 end: false
218 });
219 });
220}
221
222async function createTempUpdateFile(name, cacheDir, log) {
223 // https://github.com/electron-userland/electron-builder/pull/2474#issuecomment-366481912
224 let nameCounter = 0;
225 let result = path.join(cacheDir, name);
226
227 for (let i = 0; i < 3; i++) {
228 try {
229 await (0, _fsExtra().unlink)(result);
230 return result;
231 } catch (e) {
232 if (e.code === "ENOENT") {
233 return result;
234 }
235
236 log.warn(`Error on remove temp update file: ${e}`);
237 result = path.join(cacheDir, `${nameCounter++}-${name}`);
238 }
239 }
240
241 return result;
242}
243// __ts-babel@6.0.4
244//# sourceMappingURL=DownloadedUpdateHelper.js.map
\No newline at end of file