electron-incremental-update 0.7.1 → 0.7.3

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.
@@ -1,5 +1,5 @@
1
1
  // src/crypto.ts
2
- import { constants, createCipheriv, createDecipheriv, createHash, createSign, createVerify } from "node:crypto";
2
+ import { createCipheriv, createDecipheriv, createHash, createPrivateKey, createSign, createVerify } from "node:crypto";
3
3
  import { Buffer } from "node:buffer";
4
4
  function encrypt(plainText, key2, iv) {
5
5
  const cipher = createCipheriv("aes-256-cbc", key2, iv);
@@ -18,11 +18,7 @@ function key(data, length) {
18
18
  return Buffer.from(hash).subarray(0, length);
19
19
  }
20
20
  var signature = (buffer, privateKey, cert, version) => {
21
- const sig = createSign("RSA-SHA256").update(buffer).sign({
22
- key: privateKey,
23
- padding: constants.RSA_PKCS1_PADDING,
24
- saltLength: constants.RSA_PSS_SALTLEN_DIGEST
25
- }, "base64");
21
+ const sig = createSign("RSA-SHA256").update(buffer).sign(createPrivateKey(privateKey), "base64");
26
22
  return encrypt(`${sig}%${version}`, key(cert, 32), key(buffer, 16));
27
23
  };
28
24
  var verify = (buffer, signature2, cert) => {
package/dist/index.js CHANGED
@@ -210,24 +210,24 @@ function createUpdater({
210
210
  } = {}
211
211
  }) {
212
212
  const updater = new import_node_events.EventEmitter();
213
- let signature = "";
213
+ let signature, version;
214
214
  const asarPath = getProductAsarPath(productName);
215
215
  const gzipPath = `${asarPath}.gz`;
216
216
  const tmpFilePath = gzipPath.replace(".asar.gz", ".tmp.asar");
217
217
  function log(msg) {
218
218
  debug && updater.emit("debug", msg);
219
219
  }
220
- function needUpdate(version) {
220
+ function needUpdate(version2) {
221
221
  if (!import_electron3.app.isPackaged) {
222
222
  log("in dev mode, no need to update");
223
223
  return false;
224
224
  }
225
225
  const currentVersion = getEntryVersion();
226
- log(`check update: current version is ${currentVersion}, new version is ${version}`);
226
+ log(`check update: current version is ${currentVersion}, new version is ${version2}`);
227
227
  const _compare = compareVersion ?? compareVersionDefault;
228
- return _compare(currentVersion, version);
228
+ return _compare(currentVersion, version2);
229
229
  }
230
- async function parseData(format, data) {
230
+ async function parseData(format, data, version2) {
231
231
  if ((0, import_node_fs2.existsSync)(tmpFilePath)) {
232
232
  log(`remove tmp file: ${tmpFilePath}`);
233
233
  await (0, import_promises.rm)(tmpFilePath);
@@ -258,7 +258,7 @@ function createUpdater({
258
258
  } : {
259
259
  name: "releaseAsarURL",
260
260
  url: _release,
261
- repoFallback: `${repository}/releases/download/latest/${productName}.asar.gz`,
261
+ repoFallback: `${repository}/releases/download/v${version2}/${productName}-${version2}.asar.gz`,
262
262
  fn: downloadBuffer ?? downloadBufferDefault
263
263
  };
264
264
  data ??= info.url;
@@ -267,6 +267,9 @@ function createUpdater({
267
267
  if (!repository) {
268
268
  throw new Error(`${info.name} or repository are not set`);
269
269
  }
270
+ if (format === "buffer" && !version2) {
271
+ throw new Error("version are not set");
272
+ }
270
273
  data = info.repoFallback;
271
274
  }
272
275
  log(`download ${format} from ${data}`);
@@ -280,15 +283,16 @@ function createUpdater({
280
283
  updater.setDebug = (isDebug) => debug = isDebug;
281
284
  updater.checkUpdate = async (data) => {
282
285
  try {
283
- const { signature: _sig, size, version } = await parseData("json", data);
284
- log(`checked version: ${version}, size: ${size}, signature: ${_sig}`);
285
- if (!needUpdate(version)) {
286
- log(`update unavailable: ${version}`);
286
+ const { signature: _sig, size, version: _ver } = await parseData("json", data);
287
+ log(`checked version: ${_ver}, size: ${size}, signature: ${_sig}`);
288
+ if (!needUpdate(_ver)) {
289
+ log(`update unavailable: ${_ver}`);
287
290
  return void 0;
288
291
  } else {
289
- log(`update available: ${version}`);
292
+ log(`update available: ${_ver}`);
290
293
  signature = _sig;
291
- return { size, version };
294
+ version = _ver;
295
+ return { size, version: _ver };
292
296
  }
293
297
  } catch (error) {
294
298
  log(error);
@@ -301,29 +305,29 @@ function createUpdater({
301
305
  if (!_sig) {
302
306
  throw new Error("signature are not set, please checkUpdate first or set the second parameter");
303
307
  }
304
- const buffer = await parseData("buffer", data);
308
+ const buffer = await parseData("buffer", data, version);
305
309
  log("verify start");
306
310
  const _verify = verifySignaure ?? verify;
307
- const version = _verify(buffer, _sig, SIGNATURE_CERT);
308
- if (!version) {
311
+ const _ver = _verify(buffer, _sig, SIGNATURE_CERT);
312
+ if (!_ver) {
309
313
  throw new Error("verify failed, invalid signature");
310
314
  }
311
315
  log("verify success");
312
- if (!needUpdate(version)) {
313
- throw new Error(`update unavailable: ${version}`);
316
+ if (!needUpdate(_ver)) {
317
+ throw new Error(`update unavailable: ${_ver}`);
314
318
  }
315
319
  log(`write file: ${gzipPath}`);
316
320
  await (0, import_promises.writeFile)(gzipPath, buffer);
317
321
  log(`extract file: ${gzipPath}`);
318
322
  await unzipFile(gzipPath, tmpFilePath);
319
323
  const asarVersion = await (0, import_promises.readFile)((0, import_node_path2.resolve)(tmpFilePath, "version"), "utf8");
320
- if (asarVersion !== version) {
324
+ if (asarVersion !== _ver) {
321
325
  (0, import_node_fs2.rmSync)(tmpFilePath);
322
- throw new Error(`update failed: asar version is ${asarVersion}, but it should be ${version}`);
326
+ throw new Error(`update failed: asar version is ${asarVersion}, but it should be ${_ver}`);
323
327
  } else {
324
328
  await (0, import_promises.rename)(tmpFilePath, asarPath);
325
329
  }
326
- log(`update success, version: ${version}`);
330
+ log(`update success, version: ${_ver}`);
327
331
  signature = "";
328
332
  return true;
329
333
  } catch (error) {
package/dist/index.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  verify
3
- } from "./chunk-3YKEHZAU.mjs";
3
+ } from "./chunk-Q2K52LOG.mjs";
4
4
  import {
5
5
  __require,
6
6
  getEntryVersion,
@@ -132,24 +132,24 @@ function createUpdater({
132
132
  } = {}
133
133
  }) {
134
134
  const updater = new EventEmitter();
135
- let signature = "";
135
+ let signature, version;
136
136
  const asarPath = getProductAsarPath(productName);
137
137
  const gzipPath = `${asarPath}.gz`;
138
138
  const tmpFilePath = gzipPath.replace(".asar.gz", ".tmp.asar");
139
139
  function log(msg) {
140
140
  debug && updater.emit("debug", msg);
141
141
  }
142
- function needUpdate(version) {
142
+ function needUpdate(version2) {
143
143
  if (!app.isPackaged) {
144
144
  log("in dev mode, no need to update");
145
145
  return false;
146
146
  }
147
147
  const currentVersion = getEntryVersion();
148
- log(`check update: current version is ${currentVersion}, new version is ${version}`);
148
+ log(`check update: current version is ${currentVersion}, new version is ${version2}`);
149
149
  const _compare = compareVersion ?? compareVersionDefault;
150
- return _compare(currentVersion, version);
150
+ return _compare(currentVersion, version2);
151
151
  }
152
- async function parseData(format, data) {
152
+ async function parseData(format, data, version2) {
153
153
  if (existsSync(tmpFilePath)) {
154
154
  log(`remove tmp file: ${tmpFilePath}`);
155
155
  await rm(tmpFilePath);
@@ -180,7 +180,7 @@ function createUpdater({
180
180
  } : {
181
181
  name: "releaseAsarURL",
182
182
  url: _release,
183
- repoFallback: `${repository}/releases/download/latest/${productName}.asar.gz`,
183
+ repoFallback: `${repository}/releases/download/v${version2}/${productName}-${version2}.asar.gz`,
184
184
  fn: downloadBuffer ?? downloadBufferDefault
185
185
  };
186
186
  data ??= info.url;
@@ -189,6 +189,9 @@ function createUpdater({
189
189
  if (!repository) {
190
190
  throw new Error(`${info.name} or repository are not set`);
191
191
  }
192
+ if (format === "buffer" && !version2) {
193
+ throw new Error("version are not set");
194
+ }
192
195
  data = info.repoFallback;
193
196
  }
194
197
  log(`download ${format} from ${data}`);
@@ -202,15 +205,16 @@ function createUpdater({
202
205
  updater.setDebug = (isDebug) => debug = isDebug;
203
206
  updater.checkUpdate = async (data) => {
204
207
  try {
205
- const { signature: _sig, size, version } = await parseData("json", data);
206
- log(`checked version: ${version}, size: ${size}, signature: ${_sig}`);
207
- if (!needUpdate(version)) {
208
- log(`update unavailable: ${version}`);
208
+ const { signature: _sig, size, version: _ver } = await parseData("json", data);
209
+ log(`checked version: ${_ver}, size: ${size}, signature: ${_sig}`);
210
+ if (!needUpdate(_ver)) {
211
+ log(`update unavailable: ${_ver}`);
209
212
  return void 0;
210
213
  } else {
211
- log(`update available: ${version}`);
214
+ log(`update available: ${_ver}`);
212
215
  signature = _sig;
213
- return { size, version };
216
+ version = _ver;
217
+ return { size, version: _ver };
214
218
  }
215
219
  } catch (error) {
216
220
  log(error);
@@ -223,29 +227,29 @@ function createUpdater({
223
227
  if (!_sig) {
224
228
  throw new Error("signature are not set, please checkUpdate first or set the second parameter");
225
229
  }
226
- const buffer = await parseData("buffer", data);
230
+ const buffer = await parseData("buffer", data, version);
227
231
  log("verify start");
228
232
  const _verify = verifySignaure ?? verify;
229
- const version = _verify(buffer, _sig, SIGNATURE_CERT);
230
- if (!version) {
233
+ const _ver = _verify(buffer, _sig, SIGNATURE_CERT);
234
+ if (!_ver) {
231
235
  throw new Error("verify failed, invalid signature");
232
236
  }
233
237
  log("verify success");
234
- if (!needUpdate(version)) {
235
- throw new Error(`update unavailable: ${version}`);
238
+ if (!needUpdate(_ver)) {
239
+ throw new Error(`update unavailable: ${_ver}`);
236
240
  }
237
241
  log(`write file: ${gzipPath}`);
238
242
  await writeFile(gzipPath, buffer);
239
243
  log(`extract file: ${gzipPath}`);
240
244
  await unzipFile(gzipPath, tmpFilePath);
241
245
  const asarVersion = await readFile(resolve(tmpFilePath, "version"), "utf8");
242
- if (asarVersion !== version) {
246
+ if (asarVersion !== _ver) {
243
247
  rmSync(tmpFilePath);
244
- throw new Error(`update failed: asar version is ${asarVersion}, but it should be ${version}`);
248
+ throw new Error(`update failed: asar version is ${asarVersion}, but it should be ${_ver}`);
245
249
  } else {
246
250
  await rename(tmpFilePath, asarPath);
247
251
  }
248
- log(`update success, version: ${version}`);
252
+ log(`update success, version: ${_ver}`);
249
253
  signature = "";
250
254
  return true;
251
255
  } catch (error) {
package/dist/vite.d.mts CHANGED
@@ -1,10 +1,18 @@
1
1
  import { Plugin } from 'vite';
2
2
  import { Buffer } from 'node:buffer';
3
- import { DistinguishedName } from '@cyyynthia/jscert';
4
3
 
5
- type FunctionGenerateKeyPair = (keyLength: number, subject: DistinguishedName, expires: Date) => {
6
- privateKey: string;
7
- cert: string;
4
+ type DistinguishedName = {
5
+ countryName?: string;
6
+ stateOrProvinceName?: string;
7
+ localityName?: string;
8
+ organizationName?: string;
9
+ organizationalUnitName?: string;
10
+ commonName?: string;
11
+ serialNumber?: string;
12
+ title?: string;
13
+ description?: string;
14
+ businessCategory?: string;
15
+ emailAddress?: string;
8
16
  };
9
17
  type FunctionGenerateSignature = (buffer: Buffer, privateKey: string, cert: string, version: string) => string;
10
18
  type Options = {
@@ -47,6 +55,11 @@ type Options = {
47
55
  * @default `release/${productName}.asar`
48
56
  */
49
57
  asarOutputPath?: string;
58
+ /**
59
+ * Path to gzipped asar file
60
+ * @default `release/${productName}-${version}.asar.gz`
61
+ */
62
+ gzipPath?: string;
50
63
  /**
51
64
  * Path to electron build output
52
65
  * @default `dist-electron`
@@ -93,26 +106,17 @@ type Options = {
93
106
  /**
94
107
  * the subject of the certificate
95
108
  *
96
- * @default { commonName: productName, organization: `org.${productName}` }
109
+ * @default { commonName: productName, organizationName: `org.${productName}` }
97
110
  */
98
111
  subject?: DistinguishedName;
99
112
  /**
100
- * expires of the certificate
101
- * - `Date`: expire date
102
- * - `number`: expire duration in seconds
113
+ * expire days of the certificate
103
114
  *
104
- * @default Date.now() + 365 * 864e5 (1 year)
115
+ * @default 365
105
116
  */
106
- expires?: Date | number;
117
+ days?: number;
107
118
  };
108
119
  overrideFunctions?: {
109
- /**
110
- * custom key pair generate function {@link FunctionGenerateKeyPair}
111
- * @param keyLength key length
112
- * @param subject subject info
113
- * @param expires expire date
114
- */
115
- generateKeyPair?: FunctionGenerateKeyPair;
116
120
  /**
117
121
  * custom signature generate function {@link FunctionGenerateSignature}
118
122
  * @param buffer file buffer
package/dist/vite.d.ts CHANGED
@@ -1,10 +1,18 @@
1
1
  import { Plugin } from 'vite';
2
2
  import { Buffer } from 'node:buffer';
3
- import { DistinguishedName } from '@cyyynthia/jscert';
4
3
 
5
- type FunctionGenerateKeyPair = (keyLength: number, subject: DistinguishedName, expires: Date) => {
6
- privateKey: string;
7
- cert: string;
4
+ type DistinguishedName = {
5
+ countryName?: string;
6
+ stateOrProvinceName?: string;
7
+ localityName?: string;
8
+ organizationName?: string;
9
+ organizationalUnitName?: string;
10
+ commonName?: string;
11
+ serialNumber?: string;
12
+ title?: string;
13
+ description?: string;
14
+ businessCategory?: string;
15
+ emailAddress?: string;
8
16
  };
9
17
  type FunctionGenerateSignature = (buffer: Buffer, privateKey: string, cert: string, version: string) => string;
10
18
  type Options = {
@@ -47,6 +55,11 @@ type Options = {
47
55
  * @default `release/${productName}.asar`
48
56
  */
49
57
  asarOutputPath?: string;
58
+ /**
59
+ * Path to gzipped asar file
60
+ * @default `release/${productName}-${version}.asar.gz`
61
+ */
62
+ gzipPath?: string;
50
63
  /**
51
64
  * Path to electron build output
52
65
  * @default `dist-electron`
@@ -93,26 +106,17 @@ type Options = {
93
106
  /**
94
107
  * the subject of the certificate
95
108
  *
96
- * @default { commonName: productName, organization: `org.${productName}` }
109
+ * @default { commonName: productName, organizationName: `org.${productName}` }
97
110
  */
98
111
  subject?: DistinguishedName;
99
112
  /**
100
- * expires of the certificate
101
- * - `Date`: expire date
102
- * - `number`: expire duration in seconds
113
+ * expire days of the certificate
103
114
  *
104
- * @default Date.now() + 365 * 864e5 (1 year)
115
+ * @default 365
105
116
  */
106
- expires?: Date | number;
117
+ days?: number;
107
118
  };
108
119
  overrideFunctions?: {
109
- /**
110
- * custom key pair generate function {@link FunctionGenerateKeyPair}
111
- * @param keyLength key length
112
- * @param subject subject info
113
- * @param expires expire date
114
- */
115
- generateKeyPair?: FunctionGenerateKeyPair;
116
120
  /**
117
121
  * custom signature generate function {@link FunctionGenerateSignature}
118
122
  * @param buffer file buffer
package/dist/vite.js CHANGED
@@ -53,11 +53,7 @@ function key(data, length) {
53
53
  return import_node_buffer.Buffer.from(hash).subarray(0, length);
54
54
  }
55
55
  var signature = (buffer, privateKey, cert, version) => {
56
- const sig = (0, import_node_crypto.createSign)("RSA-SHA256").update(buffer).sign({
57
- key: privateKey,
58
- padding: import_node_crypto.constants.RSA_PKCS1_PADDING,
59
- saltLength: import_node_crypto.constants.RSA_PSS_SALTLEN_DIGEST
60
- }, "base64");
56
+ const sig = (0, import_node_crypto.createSign)("RSA-SHA256").update(buffer).sign((0, import_node_crypto.createPrivateKey)(privateKey), "base64");
61
57
  return encrypt(`${sig}%${version}`, key(cert, 32), key(buffer, 16));
62
58
  };
63
59
 
@@ -99,23 +95,24 @@ async function pack(dir, target) {
99
95
  async function buildAsar({
100
96
  version,
101
97
  asarOutputPath,
98
+ gzipPath,
102
99
  electronDistPath,
103
100
  rendererDistPath
104
101
  }) {
105
102
  await (0, import_promises.rename)(rendererDistPath, `${electronDistPath}/renderer`);
106
103
  await (0, import_promises.writeFile)(`${electronDistPath}/version`, version);
107
104
  await pack(electronDistPath, asarOutputPath);
108
- await zipFile(asarOutputPath);
105
+ await zipFile(asarOutputPath, gzipPath);
109
106
  }
110
107
  async function buildVersion({
111
- asarOutputPath,
108
+ gzipPath,
112
109
  versionPath,
113
110
  privateKey,
114
111
  cert,
115
112
  version,
116
113
  generateSignature
117
114
  }) {
118
- const buffer = await (0, import_promises.readFile)(`${asarOutputPath}.gz`);
115
+ const buffer = await (0, import_promises.readFile)(gzipPath);
119
116
  const _func = generateSignature ?? signature;
120
117
  await (0, import_promises.writeFile)(versionPath, JSON.stringify({
121
118
  signature: _func(buffer, privateKey, cert, version),
@@ -138,24 +135,51 @@ async function buildEntry({
138
135
  });
139
136
  }
140
137
 
138
+ // src/build-plugins/option.ts
139
+ var import_ci_info = require("ci-info");
140
+
141
141
  // src/build-plugins/key.ts
142
142
  var import_node_fs2 = require("fs");
143
143
  var import_node_path2 = require("path");
144
144
  var import_node_os = require("os");
145
- var import_node_crypto2 = require("crypto");
146
- var import_jscert = require("@cyyynthia/jscert");
147
- function generateCert(privateKey, dn, expires) {
148
- const csr = new import_jscert.CertificateSigningRequest(dn, privateKey, { digest: "sha256" });
149
- return csr.createSelfSignedCertificate(expires).toPem();
145
+ var import_node_child_process = require("child_process");
146
+ function generateKeyPair(keyLength, subject, days, privateKeyPath, certPath) {
147
+ const starter = `try {
148
+ require('selfsigned')
149
+ } catch (e) {
150
+ console.error('to generate private key, please run "npm install --dev selfsigned"')
150
151
  }
151
- function generateKeyPairDefault(length, subjects, expires) {
152
- const { privateKey: _key } = (0, import_node_crypto2.generateKeyPairSync)("rsa", { modulusLength: length });
153
- const cert = generateCert(_key, subjects, expires);
154
- const privateKey = _key.export({ type: "pkcs1", format: "pem" });
155
- return {
156
- privateKey,
157
- cert
158
- };
152
+ try {
153
+ const { existsSync, mkdirSync, writeFileSync } = require('node:fs')
154
+ const { dirname } = require('node:path')
155
+ const { generate } = require('selfsigned')
156
+ const privateKeyPath = '${privateKeyPath.replace(/\\/g, "/")}'
157
+ const certPath = '${certPath.replace(/\\/g, "/")}'
158
+ const privateKeyDir = dirname(privateKeyPath)
159
+ existsSync(privateKeyDir) || mkdirSync(privateKeyDir, { recursive: true })
160
+ const certDir = dirname(certPath)
161
+ existsSync(certDir) || mkdirSync(certDir, { recursive: true })
162
+
163
+ const { cert, private: privateKey } = generate(${JSON.stringify(subject)}, {
164
+ keySize: ${keyLength}, algorithm: 'sha256', days: ${days},
165
+ })
166
+
167
+ writeFileSync(privateKeyPath, privateKey.replace(/\\r/g, ''))
168
+ writeFileSync(certPath, cert.replace(/\\r/g, ''))
169
+ } catch (e) {
170
+ console.error(e)
171
+ process.exit(-1)
172
+ } finally {
173
+ process.exit(0)
174
+ }
175
+ `;
176
+ const fileName = "key-gen.js";
177
+ (0, import_node_fs2.writeFileSync)(`./${fileName}`, starter);
178
+ try {
179
+ (0, import_node_child_process.execSync)(`npx electron ${fileName}`, { stdio: "inherit" });
180
+ } finally {
181
+ (0, import_node_fs2.rmSync)(`./${fileName}`);
182
+ }
159
183
  }
160
184
  function writeCertToMain(entryPath, cert) {
161
185
  const file = (0, import_node_fs2.readFileSync)(entryPath, "utf-8");
@@ -182,38 +206,37 @@ function writeCertToMain(entryPath, cert) {
182
206
  }
183
207
  (0, import_node_fs2.writeFileSync)(entryPath, replaced);
184
208
  }
185
- function getKeys({
209
+ function parseKeys({
186
210
  keyLength,
187
211
  privateKeyPath,
188
212
  certPath,
189
213
  entryPath,
190
214
  subject,
191
- expires,
192
- generateKeyPair
215
+ days
193
216
  }) {
194
217
  const keysDir = (0, import_node_path2.dirname)(privateKeyPath);
195
218
  !(0, import_node_fs2.existsSync)(keysDir) && (0, import_node_fs2.mkdirSync)(keysDir);
196
- let privateKey, cert;
197
219
  if (!(0, import_node_fs2.existsSync)(privateKeyPath) || !(0, import_node_fs2.existsSync)(certPath)) {
198
- const _func = generateKeyPair ?? generateKeyPairDefault;
199
- const keys = _func(keyLength, subject, expires);
200
- privateKey = keys.privateKey;
201
- cert = keys.cert;
202
- (0, import_node_fs2.writeFileSync)(privateKeyPath, privateKey);
203
- (0, import_node_fs2.writeFileSync)(certPath, cert);
204
- } else {
205
- privateKey = (0, import_node_fs2.readFileSync)(privateKeyPath, "utf-8");
206
- cert = (0, import_node_fs2.readFileSync)(certPath, "utf-8");
220
+ generateKeyPair(keyLength, parseSubjects(subject), days, privateKeyPath, certPath);
207
221
  }
222
+ const privateKey = (0, import_node_fs2.readFileSync)(privateKeyPath, "utf-8");
223
+ const cert = (0, import_node_fs2.readFileSync)(certPath, "utf-8");
208
224
  writeCertToMain(entryPath, cert);
209
225
  return {
210
226
  privateKey,
211
227
  cert
212
228
  };
213
229
  }
230
+ function parseSubjects(subject) {
231
+ const ret = [];
232
+ Object.keys(subject).forEach((name) => {
233
+ const value = subject[name];
234
+ value && ret.push({ name, value });
235
+ });
236
+ return ret;
237
+ }
214
238
 
215
239
  // src/build-plugins/option.ts
216
- var import_ci_info = require("ci-info");
217
240
  function parseOptions(options) {
218
241
  const {
219
242
  isBuild,
@@ -223,7 +246,8 @@ function parseOptions(options) {
223
246
  paths: {
224
247
  entryPath = "electron/app.ts",
225
248
  entryOutputPath = "app.js",
226
- asarOutputPath = `release/${productName}-${version}.asar`,
249
+ asarOutputPath = `release/${productName}.asar`,
250
+ gzipPath = `release/${productName}-${version}.asar.gz`,
227
251
  electronDistPath = "dist-electron",
228
252
  rendererDistPath = "dist",
229
253
  versionPath = "version.json"
@@ -236,20 +260,18 @@ function parseOptions(options) {
236
260
  overrideFunctions = {}
237
261
  } = {}
238
262
  } = options;
239
- const {
240
- generateKeyPair,
241
- generateSignature
242
- } = overrideFunctions;
263
+ const { generateSignature } = overrideFunctions;
243
264
  let {
244
265
  subject = {
245
266
  commonName: productName,
246
- organization: `org.${productName}`
267
+ organizationName: `org.${productName}`
247
268
  },
248
- expires = Date.now() + 365 * 864e5
269
+ days = 365
249
270
  } = certInfo;
250
271
  const buildAsarOption = {
251
272
  version,
252
273
  asarOutputPath,
274
+ gzipPath,
253
275
  electronDistPath,
254
276
  rendererDistPath
255
277
  };
@@ -260,21 +282,17 @@ function parseOptions(options) {
260
282
  };
261
283
  let buildVersionOption;
262
284
  if (!import_ci_info.isCI) {
263
- if (typeof expires === "number") {
264
- expires = new Date(Date.now() + expires);
265
- }
266
- const { privateKey, cert } = getKeys({
285
+ const { privateKey, cert } = parseKeys({
267
286
  keyLength,
268
287
  privateKeyPath,
269
288
  certPath,
270
289
  entryPath,
271
290
  subject,
272
- expires,
273
- generateKeyPair
291
+ days
274
292
  });
275
293
  buildVersionOption = {
276
294
  version,
277
- asarOutputPath,
295
+ gzipPath,
278
296
  privateKey,
279
297
  cert,
280
298
  versionPath,
package/dist/vite.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  signature
3
- } from "./chunk-3YKEHZAU.mjs";
3
+ } from "./chunk-Q2K52LOG.mjs";
4
4
  import {
5
5
  zipFile
6
6
  } from "./chunk-CRBEZBU5.mjs";
@@ -31,23 +31,24 @@ async function pack(dir, target) {
31
31
  async function buildAsar({
32
32
  version,
33
33
  asarOutputPath,
34
+ gzipPath,
34
35
  electronDistPath,
35
36
  rendererDistPath
36
37
  }) {
37
38
  await rename(rendererDistPath, `${electronDistPath}/renderer`);
38
39
  await writeFile(`${electronDistPath}/version`, version);
39
40
  await pack(electronDistPath, asarOutputPath);
40
- await zipFile(asarOutputPath);
41
+ await zipFile(asarOutputPath, gzipPath);
41
42
  }
42
43
  async function buildVersion({
43
- asarOutputPath,
44
+ gzipPath,
44
45
  versionPath,
45
46
  privateKey,
46
47
  cert,
47
48
  version,
48
49
  generateSignature
49
50
  }) {
50
- const buffer = await readFile(`${asarOutputPath}.gz`);
51
+ const buffer = await readFile(gzipPath);
51
52
  const _func = generateSignature ?? signature;
52
53
  await writeFile(versionPath, JSON.stringify({
53
54
  signature: _func(buffer, privateKey, cert, version),
@@ -70,24 +71,51 @@ async function buildEntry({
70
71
  });
71
72
  }
72
73
 
74
+ // src/build-plugins/option.ts
75
+ import { isCI } from "ci-info";
76
+
73
77
  // src/build-plugins/key.ts
74
- import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
78
+ import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
75
79
  import { dirname } from "node:path";
76
80
  import { EOL } from "node:os";
77
- import { generateKeyPairSync } from "node:crypto";
78
- import { CertificateSigningRequest } from "@cyyynthia/jscert";
79
- function generateCert(privateKey, dn, expires) {
80
- const csr = new CertificateSigningRequest(dn, privateKey, { digest: "sha256" });
81
- return csr.createSelfSignedCertificate(expires).toPem();
81
+ import { execSync } from "node:child_process";
82
+ function generateKeyPair(keyLength, subject, days, privateKeyPath, certPath) {
83
+ const starter = `try {
84
+ require('selfsigned')
85
+ } catch (e) {
86
+ console.error('to generate private key, please run "npm install --dev selfsigned"')
82
87
  }
83
- function generateKeyPairDefault(length, subjects, expires) {
84
- const { privateKey: _key } = generateKeyPairSync("rsa", { modulusLength: length });
85
- const cert = generateCert(_key, subjects, expires);
86
- const privateKey = _key.export({ type: "pkcs1", format: "pem" });
87
- return {
88
- privateKey,
89
- cert
90
- };
88
+ try {
89
+ const { existsSync, mkdirSync, writeFileSync } = require('node:fs')
90
+ const { dirname } = require('node:path')
91
+ const { generate } = require('selfsigned')
92
+ const privateKeyPath = '${privateKeyPath.replace(/\\/g, "/")}'
93
+ const certPath = '${certPath.replace(/\\/g, "/")}'
94
+ const privateKeyDir = dirname(privateKeyPath)
95
+ existsSync(privateKeyDir) || mkdirSync(privateKeyDir, { recursive: true })
96
+ const certDir = dirname(certPath)
97
+ existsSync(certDir) || mkdirSync(certDir, { recursive: true })
98
+
99
+ const { cert, private: privateKey } = generate(${JSON.stringify(subject)}, {
100
+ keySize: ${keyLength}, algorithm: 'sha256', days: ${days},
101
+ })
102
+
103
+ writeFileSync(privateKeyPath, privateKey.replace(/\\r/g, ''))
104
+ writeFileSync(certPath, cert.replace(/\\r/g, ''))
105
+ } catch (e) {
106
+ console.error(e)
107
+ process.exit(-1)
108
+ } finally {
109
+ process.exit(0)
110
+ }
111
+ `;
112
+ const fileName = "key-gen.js";
113
+ writeFileSync(`./${fileName}`, starter);
114
+ try {
115
+ execSync(`npx electron ${fileName}`, { stdio: "inherit" });
116
+ } finally {
117
+ rmSync(`./${fileName}`);
118
+ }
91
119
  }
92
120
  function writeCertToMain(entryPath, cert) {
93
121
  const file = readFileSync(entryPath, "utf-8");
@@ -114,38 +142,37 @@ function writeCertToMain(entryPath, cert) {
114
142
  }
115
143
  writeFileSync(entryPath, replaced);
116
144
  }
117
- function getKeys({
145
+ function parseKeys({
118
146
  keyLength,
119
147
  privateKeyPath,
120
148
  certPath,
121
149
  entryPath,
122
150
  subject,
123
- expires,
124
- generateKeyPair
151
+ days
125
152
  }) {
126
153
  const keysDir = dirname(privateKeyPath);
127
154
  !existsSync(keysDir) && mkdirSync(keysDir);
128
- let privateKey, cert;
129
155
  if (!existsSync(privateKeyPath) || !existsSync(certPath)) {
130
- const _func = generateKeyPair ?? generateKeyPairDefault;
131
- const keys = _func(keyLength, subject, expires);
132
- privateKey = keys.privateKey;
133
- cert = keys.cert;
134
- writeFileSync(privateKeyPath, privateKey);
135
- writeFileSync(certPath, cert);
136
- } else {
137
- privateKey = readFileSync(privateKeyPath, "utf-8");
138
- cert = readFileSync(certPath, "utf-8");
156
+ generateKeyPair(keyLength, parseSubjects(subject), days, privateKeyPath, certPath);
139
157
  }
158
+ const privateKey = readFileSync(privateKeyPath, "utf-8");
159
+ const cert = readFileSync(certPath, "utf-8");
140
160
  writeCertToMain(entryPath, cert);
141
161
  return {
142
162
  privateKey,
143
163
  cert
144
164
  };
145
165
  }
166
+ function parseSubjects(subject) {
167
+ const ret = [];
168
+ Object.keys(subject).forEach((name) => {
169
+ const value = subject[name];
170
+ value && ret.push({ name, value });
171
+ });
172
+ return ret;
173
+ }
146
174
 
147
175
  // src/build-plugins/option.ts
148
- import { isCI } from "ci-info";
149
176
  function parseOptions(options) {
150
177
  const {
151
178
  isBuild,
@@ -155,7 +182,8 @@ function parseOptions(options) {
155
182
  paths: {
156
183
  entryPath = "electron/app.ts",
157
184
  entryOutputPath = "app.js",
158
- asarOutputPath = `release/${productName}-${version}.asar`,
185
+ asarOutputPath = `release/${productName}.asar`,
186
+ gzipPath = `release/${productName}-${version}.asar.gz`,
159
187
  electronDistPath = "dist-electron",
160
188
  rendererDistPath = "dist",
161
189
  versionPath = "version.json"
@@ -168,20 +196,18 @@ function parseOptions(options) {
168
196
  overrideFunctions = {}
169
197
  } = {}
170
198
  } = options;
171
- const {
172
- generateKeyPair,
173
- generateSignature
174
- } = overrideFunctions;
199
+ const { generateSignature } = overrideFunctions;
175
200
  let {
176
201
  subject = {
177
202
  commonName: productName,
178
- organization: `org.${productName}`
203
+ organizationName: `org.${productName}`
179
204
  },
180
- expires = Date.now() + 365 * 864e5
205
+ days = 365
181
206
  } = certInfo;
182
207
  const buildAsarOption = {
183
208
  version,
184
209
  asarOutputPath,
210
+ gzipPath,
185
211
  electronDistPath,
186
212
  rendererDistPath
187
213
  };
@@ -192,21 +218,17 @@ function parseOptions(options) {
192
218
  };
193
219
  let buildVersionOption;
194
220
  if (!isCI) {
195
- if (typeof expires === "number") {
196
- expires = new Date(Date.now() + expires);
197
- }
198
- const { privateKey, cert } = getKeys({
221
+ const { privateKey, cert } = parseKeys({
199
222
  keyLength,
200
223
  privateKeyPath,
201
224
  certPath,
202
225
  entryPath,
203
226
  subject,
204
- expires,
205
- generateKeyPair
227
+ days
206
228
  });
207
229
  buildVersionOption = {
208
230
  version,
209
- asarOutputPath,
231
+ gzipPath,
210
232
  privateKey,
211
233
  cert,
212
234
  versionPath,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "electron-incremental-update",
3
3
  "author": "subframe7536",
4
- "version": "0.7.1",
4
+ "version": "0.7.3",
5
5
  "description": "electron incremental update tools, powered by vite",
6
6
  "scripts": {
7
7
  "build": "tsup && node fix-module.js",
@@ -50,14 +50,15 @@
50
50
  "bumpp": "^9.1.1",
51
51
  "electron": "^25.2.0",
52
52
  "eslint": "^8.43.0",
53
- "fs-jetpack": "^5.1.0",
54
53
  "tsup": "^7.1.0",
55
54
  "typescript": "^5.1.5",
56
55
  "vite": "^4.3.9",
57
56
  "vitest": "^0.32.2"
58
57
  },
59
58
  "dependencies": {
60
- "@cyyynthia/jscert": "^0.1.2",
61
59
  "ci-info": "^3.8.0"
60
+ },
61
+ "peerDependencies": {
62
+ "selfsigned": "^2.1.1"
62
63
  }
63
64
  }