electron-incremental-update 0.5.1 → 0.6.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.
package/dist/vite.cjs CHANGED
@@ -11,9 +11,9 @@ var __export = (target, all) => {
11
11
  };
12
12
  var __copyProps = (to, from, except, desc) => {
13
13
  if (from && typeof from === "object" || typeof from === "function") {
14
- for (let key of __getOwnPropNames(from))
15
- if (!__hasOwnProp.call(to, key) && key !== except)
16
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
14
+ for (let key2 of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key2) && key2 !== except)
16
+ __defProp(to, key2, { get: () => from[key2], enumerable: !(desc = __getOwnPropDesc(from, key2)) || desc.enumerable });
17
17
  }
18
18
  return to;
19
19
  };
@@ -35,44 +35,36 @@ __export(vite_exports, {
35
35
  module.exports = __toCommonJS(vite_exports);
36
36
  var import_vite = require("vite");
37
37
 
38
- // src/build-plugins/asar.ts
38
+ // src/build-plugins/build.ts
39
39
  var import_node_fs = require("fs");
40
40
  var import_promises = require("fs/promises");
41
41
  var import_node_zlib = __toESM(require("zlib"), 1);
42
+ var import_esbuild = require("esbuild");
42
43
 
43
44
  // src/crypto.ts
44
45
  var import_node_crypto = require("crypto");
45
46
  var import_node_buffer = require("buffer");
46
47
  var aesEncode = "base64url";
47
- function generateRSA(length = 2048) {
48
- const pair = (0, import_node_crypto.generateKeyPairSync)("rsa", { modulusLength: length });
49
- const privateKey = pair.privateKey.export({ type: "pkcs1", format: "pem" });
50
- const publicKey = pair.publicKey.export({ type: "pkcs1", format: "pem" });
51
- return {
52
- privateKey,
53
- publicKey
54
- };
55
- }
56
- function encrypt(plainText, key, iv) {
57
- const cipher = (0, import_node_crypto.createCipheriv)("aes-256-cbc", key, iv);
48
+ function encrypt(plainText, key2, iv) {
49
+ const cipher = (0, import_node_crypto.createCipheriv)("aes-256-cbc", key2, iv);
58
50
  let encrypted = cipher.update(plainText, "utf8", aesEncode);
59
51
  encrypted += cipher.final(aesEncode);
60
52
  return encrypted;
61
53
  }
62
- function generateKey(data, length) {
54
+ function key(data, length) {
63
55
  const hash = (0, import_node_crypto.createHash)("SHA256").update(data).digest("binary");
64
56
  return import_node_buffer.Buffer.from(hash).subarray(0, length);
65
57
  }
66
- function signature(buffer, privateKey, publicKey) {
58
+ function signature(buffer, privateKey, cert, version) {
67
59
  const sig = (0, import_node_crypto.createSign)("RSA-SHA256").update(buffer).sign({
68
60
  key: privateKey,
69
61
  padding: import_node_crypto.constants.RSA_PKCS1_PADDING,
70
62
  saltLength: import_node_crypto.constants.RSA_PSS_SALTLEN_DIGEST
71
63
  }, "base64");
72
- return encrypt(sig, generateKey(publicKey, 32), generateKey(buffer, 16));
64
+ return encrypt(`${sig}%${version}`, key(cert, 32), key(buffer, 16));
73
65
  }
74
66
 
75
- // src/build-plugins/asar.ts
67
+ // src/build-plugins/build.ts
76
68
  function gzipFile(filePath) {
77
69
  return new Promise((resolve, reject) => {
78
70
  const gzip = import_node_zlib.default.createGzip();
@@ -109,23 +101,20 @@ async function buildAsar({
109
101
  await pack(electronDistPath, asarOutputPath);
110
102
  await gzipFile(asarOutputPath);
111
103
  }
112
- async function generateVersion({
104
+ async function buildVersion({
113
105
  asarOutputPath,
114
106
  versionPath,
115
107
  privateKey,
116
- publicKey,
108
+ cert,
117
109
  version
118
110
  }) {
119
111
  const buffer = await (0, import_promises.readFile)(`${asarOutputPath}.gz`);
120
112
  await (0, import_promises.writeFile)(versionPath, JSON.stringify({
121
- signature: signature(buffer, privateKey, publicKey),
113
+ signature: signature(buffer, privateKey, cert, version),
122
114
  version,
123
115
  size: buffer.length
124
116
  }, null, 2));
125
117
  }
126
-
127
- // src/build-plugins/entry.ts
128
- var import_esbuild = require("esbuild");
129
118
  async function buildEntry({
130
119
  entryPath,
131
120
  entryOutputPath: outfile,
@@ -145,16 +134,35 @@ async function buildEntry({
145
134
  var import_node_fs2 = require("fs");
146
135
  var import_node_path = require("path");
147
136
  var import_node_os = require("os");
148
- function generateKeyFile(privateKeyPath, publicKeyPath, length) {
149
- const ret = generateRSA(length);
150
- (0, import_node_fs2.writeFileSync)(privateKeyPath, ret.privateKey);
151
- (0, import_node_fs2.writeFileSync)(publicKeyPath, ret.publicKey);
152
- return ret;
137
+ var import_node_crypto2 = require("crypto");
138
+ var import_jscert = require("@cyyynthia/jscert");
139
+ function generateCert(privateKey) {
140
+ const dn = {
141
+ country: "zh-CN",
142
+ state: "zj",
143
+ locality: "hz",
144
+ organization: "test",
145
+ organizationalUnit: "test unit",
146
+ commonName: "test.test",
147
+ emailAddress: "test@example.com"
148
+ };
149
+ const csr = new import_jscert.CertificateSigningRequest(dn, privateKey, { digest: "sha256" });
150
+ const expiry = new Date(Date.now() + 365 * 864e5);
151
+ return csr.createSelfSignedCertificate(expiry).toPem();
152
+ }
153
+ function generateKeys(length = 2048) {
154
+ const { privateKey: _key } = (0, import_node_crypto2.generateKeyPairSync)("rsa", { modulusLength: length });
155
+ const cert = generateCert(_key);
156
+ const privateKey = _key.export({ type: "pkcs1", format: "pem" });
157
+ return {
158
+ privateKey,
159
+ cert
160
+ };
153
161
  }
154
- function writePublicKeyToMain(entryPath, publicKey) {
162
+ function writeCertToMain(entryPath, cert) {
155
163
  const file = (0, import_node_fs2.readFileSync)(entryPath, "utf-8");
156
- const regex = /const SIGNATURE_PUB = ['`][\s\S]*?['`]/;
157
- const replacement = `const SIGNATURE_PUB = \`${publicKey}\``;
164
+ const regex = /const SIGNATURE_CERT = ['`][\s\S]*?['`]/;
165
+ const replacement = `const SIGNATURE_CERT = \`${cert}\``;
158
166
  let replaced = file;
159
167
  const signaturePubExists = regex.test(file);
160
168
  if (signaturePubExists) {
@@ -179,24 +187,26 @@ function writePublicKeyToMain(entryPath, publicKey) {
179
187
  function getKeys({
180
188
  keyLength,
181
189
  privateKeyPath,
182
- publicKeyPath,
190
+ certPath,
183
191
  entryPath
184
192
  }) {
185
193
  const keysDir = (0, import_node_path.dirname)(privateKeyPath);
186
194
  !(0, import_node_fs2.existsSync)(keysDir) && (0, import_node_fs2.mkdirSync)(keysDir);
187
- let privateKey, publicKey;
188
- if (!(0, import_node_fs2.existsSync)(privateKeyPath)) {
189
- const keys = generateKeyFile(privateKeyPath, publicKeyPath, keyLength);
195
+ let privateKey, cert;
196
+ if (!(0, import_node_fs2.existsSync)(privateKeyPath) || !(0, import_node_fs2.existsSync)(certPath)) {
197
+ const keys = generateKeys(keyLength);
190
198
  privateKey = keys.privateKey;
191
- publicKey = keys.publicKey;
199
+ cert = keys.cert;
200
+ (0, import_node_fs2.writeFileSync)(privateKeyPath, privateKey);
201
+ (0, import_node_fs2.writeFileSync)(certPath, cert);
192
202
  } else {
193
203
  privateKey = (0, import_node_fs2.readFileSync)(privateKeyPath, "utf-8");
194
- publicKey = (0, import_node_fs2.readFileSync)(publicKeyPath, "utf-8");
204
+ cert = (0, import_node_fs2.readFileSync)(certPath, "utf-8");
195
205
  }
196
- writePublicKeyToMain(entryPath, publicKey);
206
+ writeCertToMain(entryPath, cert);
197
207
  return {
198
208
  privateKey,
199
- publicKey
209
+ cert
200
210
  };
201
211
  }
202
212
 
@@ -207,16 +217,24 @@ function parseOptions(options) {
207
217
  const {
208
218
  entryPath = "electron/app.ts",
209
219
  entryOutputPath = "app.js",
210
- asarOutputPath = `release/${productName}.asar`,
220
+ asarOutputPath = `release/${productName}-${version}.asar`,
211
221
  electronDistPath = "dist-electron",
212
222
  rendererDistPath = "dist",
213
223
  versionPath = "version.json"
214
224
  } = paths;
215
225
  const {
216
226
  privateKeyPath = "keys/private.pem",
217
- publicKeyPath = "keys/public.pem",
218
- keyLength = 2048
227
+ certPath = "keys/cert.pem",
228
+ keyLength = 2048,
229
+ certInfo
219
230
  } = keys;
231
+ let {
232
+ subject = {
233
+ commonName: productName,
234
+ organization: `org.${productName}`
235
+ },
236
+ expires = Date.now() + 365 * 864e5
237
+ } = certInfo || {};
220
238
  const buildAsarOption = {
221
239
  version,
222
240
  asarOutputPath,
@@ -230,17 +248,22 @@ function parseOptions(options) {
230
248
  };
231
249
  let buildVersionOption;
232
250
  if (!import_ci_info.isCI) {
233
- const { privateKey, publicKey } = getKeys({
251
+ if (typeof expires === "number") {
252
+ expires = new Date(Date.now() + expires);
253
+ }
254
+ const { privateKey, cert } = getKeys({
234
255
  keyLength,
235
256
  privateKeyPath,
236
- publicKeyPath,
237
- entryPath
257
+ certPath,
258
+ entryPath,
259
+ subject,
260
+ expires
238
261
  });
239
262
  buildVersionOption = {
240
263
  version,
241
264
  asarOutputPath,
242
265
  privateKey,
243
- publicKey,
266
+ cert,
244
267
  versionPath
245
268
  };
246
269
  }
@@ -266,7 +289,7 @@ function vite_default(options) {
266
289
  }
267
290
  log.info("build asar start");
268
291
  await buildAsar(buildAsarOption);
269
- buildVersionOption && await generateVersion(buildVersionOption);
292
+ buildVersionOption && await buildVersion(buildVersionOption);
270
293
  log.info(`build asar end, output to ${asarOutputPath}`);
271
294
  }
272
295
  };
package/dist/vite.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { Plugin } from 'vite';
2
+ import { DistinguishedName } from '@cyyynthia/jscert';
2
3
 
3
4
  type Options = {
4
5
  /**
@@ -37,7 +38,7 @@ type Options = {
37
38
  entryOutputPath?: string;
38
39
  /**
39
40
  * Path to asar file
40
- * @default `release/${ProductName}.asar`
41
+ * @default `release/${productName}.asar`
41
42
  */
42
43
  asarOutputPath?: string;
43
44
  /**
@@ -69,14 +70,35 @@ type Options = {
69
70
  /**
70
71
  * Path to the pem file that contains public key
71
72
  * if not ended with .pem, it will be appended
72
- * @default 'keys/public.pem'
73
+ * @default 'keys/cert.pem'
73
74
  */
74
- publicKeyPath?: string;
75
+ certPath?: string;
75
76
  /**
76
77
  * Length of the key
77
78
  * @default 2048
78
79
  */
79
80
  keyLength?: number;
81
+ /**
82
+ * X509 certificate info
83
+ *
84
+ * only generate simple **self-signed** certificate **without extensions**
85
+ */
86
+ certInfo?: {
87
+ /**
88
+ * the subject of the certificate
89
+ *
90
+ * @default { commonName: productName, organization: `org.${productName}` }
91
+ */
92
+ subject?: DistinguishedName;
93
+ /**
94
+ * expires of the certificate
95
+ * - `Date`: expire date
96
+ * - `number`: expire duration in seconds
97
+ *
98
+ * @default Date.now() + 365 * 864e5 (1 year)
99
+ */
100
+ expires?: Date | number;
101
+ };
80
102
  };
81
103
  };
82
104
 
package/dist/vite.mjs CHANGED
@@ -1,15 +1,15 @@
1
1
  import {
2
- generateRSA,
3
2
  signature
4
- } from "./chunk-OBERMV66.mjs";
3
+ } from "./chunk-VADH6AZA.mjs";
5
4
 
6
5
  // src/vite.ts
7
6
  import { createLogger } from "vite";
8
7
 
9
- // src/build-plugins/asar.ts
8
+ // src/build-plugins/build.ts
10
9
  import { createReadStream, createWriteStream } from "node:fs";
11
10
  import { readFile, rename, writeFile } from "node:fs/promises";
12
11
  import zlib from "node:zlib";
12
+ import { build } from "esbuild";
13
13
  function gzipFile(filePath) {
14
14
  return new Promise((resolve, reject) => {
15
15
  const gzip = zlib.createGzip();
@@ -46,23 +46,20 @@ async function buildAsar({
46
46
  await pack(electronDistPath, asarOutputPath);
47
47
  await gzipFile(asarOutputPath);
48
48
  }
49
- async function generateVersion({
49
+ async function buildVersion({
50
50
  asarOutputPath,
51
51
  versionPath,
52
52
  privateKey,
53
- publicKey,
53
+ cert,
54
54
  version
55
55
  }) {
56
56
  const buffer = await readFile(`${asarOutputPath}.gz`);
57
57
  await writeFile(versionPath, JSON.stringify({
58
- signature: signature(buffer, privateKey, publicKey),
58
+ signature: signature(buffer, privateKey, cert, version),
59
59
  version,
60
60
  size: buffer.length
61
61
  }, null, 2));
62
62
  }
63
-
64
- // src/build-plugins/entry.ts
65
- import { build } from "esbuild";
66
63
  async function buildEntry({
67
64
  entryPath,
68
65
  entryOutputPath: outfile,
@@ -82,16 +79,35 @@ async function buildEntry({
82
79
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
83
80
  import { dirname } from "node:path";
84
81
  import { EOL } from "node:os";
85
- function generateKeyFile(privateKeyPath, publicKeyPath, length) {
86
- const ret = generateRSA(length);
87
- writeFileSync(privateKeyPath, ret.privateKey);
88
- writeFileSync(publicKeyPath, ret.publicKey);
89
- return ret;
82
+ import { generateKeyPairSync } from "node:crypto";
83
+ import { CertificateSigningRequest } from "@cyyynthia/jscert";
84
+ function generateCert(privateKey) {
85
+ const dn = {
86
+ country: "zh-CN",
87
+ state: "zj",
88
+ locality: "hz",
89
+ organization: "test",
90
+ organizationalUnit: "test unit",
91
+ commonName: "test.test",
92
+ emailAddress: "test@example.com"
93
+ };
94
+ const csr = new CertificateSigningRequest(dn, privateKey, { digest: "sha256" });
95
+ const expiry = new Date(Date.now() + 365 * 864e5);
96
+ return csr.createSelfSignedCertificate(expiry).toPem();
90
97
  }
91
- function writePublicKeyToMain(entryPath, publicKey) {
98
+ function generateKeys(length = 2048) {
99
+ const { privateKey: _key } = generateKeyPairSync("rsa", { modulusLength: length });
100
+ const cert = generateCert(_key);
101
+ const privateKey = _key.export({ type: "pkcs1", format: "pem" });
102
+ return {
103
+ privateKey,
104
+ cert
105
+ };
106
+ }
107
+ function writeCertToMain(entryPath, cert) {
92
108
  const file = readFileSync(entryPath, "utf-8");
93
- const regex = /const SIGNATURE_PUB = ['`][\s\S]*?['`]/;
94
- const replacement = `const SIGNATURE_PUB = \`${publicKey}\``;
109
+ const regex = /const SIGNATURE_CERT = ['`][\s\S]*?['`]/;
110
+ const replacement = `const SIGNATURE_CERT = \`${cert}\``;
95
111
  let replaced = file;
96
112
  const signaturePubExists = regex.test(file);
97
113
  if (signaturePubExists) {
@@ -116,24 +132,26 @@ function writePublicKeyToMain(entryPath, publicKey) {
116
132
  function getKeys({
117
133
  keyLength,
118
134
  privateKeyPath,
119
- publicKeyPath,
135
+ certPath,
120
136
  entryPath
121
137
  }) {
122
138
  const keysDir = dirname(privateKeyPath);
123
139
  !existsSync(keysDir) && mkdirSync(keysDir);
124
- let privateKey, publicKey;
125
- if (!existsSync(privateKeyPath)) {
126
- const keys = generateKeyFile(privateKeyPath, publicKeyPath, keyLength);
140
+ let privateKey, cert;
141
+ if (!existsSync(privateKeyPath) || !existsSync(certPath)) {
142
+ const keys = generateKeys(keyLength);
127
143
  privateKey = keys.privateKey;
128
- publicKey = keys.publicKey;
144
+ cert = keys.cert;
145
+ writeFileSync(privateKeyPath, privateKey);
146
+ writeFileSync(certPath, cert);
129
147
  } else {
130
148
  privateKey = readFileSync(privateKeyPath, "utf-8");
131
- publicKey = readFileSync(publicKeyPath, "utf-8");
149
+ cert = readFileSync(certPath, "utf-8");
132
150
  }
133
- writePublicKeyToMain(entryPath, publicKey);
151
+ writeCertToMain(entryPath, cert);
134
152
  return {
135
153
  privateKey,
136
- publicKey
154
+ cert
137
155
  };
138
156
  }
139
157
 
@@ -144,16 +162,24 @@ function parseOptions(options) {
144
162
  const {
145
163
  entryPath = "electron/app.ts",
146
164
  entryOutputPath = "app.js",
147
- asarOutputPath = `release/${productName}.asar`,
165
+ asarOutputPath = `release/${productName}-${version}.asar`,
148
166
  electronDistPath = "dist-electron",
149
167
  rendererDistPath = "dist",
150
168
  versionPath = "version.json"
151
169
  } = paths;
152
170
  const {
153
171
  privateKeyPath = "keys/private.pem",
154
- publicKeyPath = "keys/public.pem",
155
- keyLength = 2048
172
+ certPath = "keys/cert.pem",
173
+ keyLength = 2048,
174
+ certInfo
156
175
  } = keys;
176
+ let {
177
+ subject = {
178
+ commonName: productName,
179
+ organization: `org.${productName}`
180
+ },
181
+ expires = Date.now() + 365 * 864e5
182
+ } = certInfo || {};
157
183
  const buildAsarOption = {
158
184
  version,
159
185
  asarOutputPath,
@@ -167,17 +193,22 @@ function parseOptions(options) {
167
193
  };
168
194
  let buildVersionOption;
169
195
  if (!isCI) {
170
- const { privateKey, publicKey } = getKeys({
196
+ if (typeof expires === "number") {
197
+ expires = new Date(Date.now() + expires);
198
+ }
199
+ const { privateKey, cert } = getKeys({
171
200
  keyLength,
172
201
  privateKeyPath,
173
- publicKeyPath,
174
- entryPath
202
+ certPath,
203
+ entryPath,
204
+ subject,
205
+ expires
175
206
  });
176
207
  buildVersionOption = {
177
208
  version,
178
209
  asarOutputPath,
179
210
  privateKey,
180
- publicKey,
211
+ cert,
181
212
  versionPath
182
213
  };
183
214
  }
@@ -203,7 +234,7 @@ function vite_default(options) {
203
234
  }
204
235
  log.info("build asar start");
205
236
  await buildAsar(buildAsarOption);
206
- buildVersionOption && await generateVersion(buildVersionOption);
237
+ buildVersionOption && await buildVersion(buildVersionOption);
207
238
  log.info(`build asar end, output to ${asarOutputPath}`);
208
239
  }
209
240
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "electron-incremental-update",
3
- "version": "0.5.1",
3
+ "version": "0.6.1",
4
4
  "description": "electron incremental update tools, powered by vite",
5
5
  "scripts": {
6
6
  "build": "tsup",
@@ -61,6 +61,7 @@
61
61
  "vitest": "^0.32.2"
62
62
  },
63
63
  "dependencies": {
64
+ "@cyyynthia/jscert": "^0.1.2",
64
65
  "ci-info": "^3.8.0"
65
66
  }
66
67
  }