electron-incremental-update 2.0.0-beta.6 → 2.0.0-beta.8

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.js CHANGED
@@ -1,18 +1,19 @@
1
- import path2, { join, resolve, basename, dirname } from 'node:path';
2
- import fs, { rmSync, renameSync, writeFileSync, readFileSync, existsSync, cpSync, mkdirSync } from 'node:fs';
1
+ import path5 from 'node:path';
2
+ import fs3 from 'node:fs';
3
3
  import { createLogger, normalizePath, mergeConfig, createFilter } from 'vite';
4
4
  import ElectronSimple from 'vite-plugin-electron/simple';
5
5
  import { startup } from 'vite-plugin-electron';
6
6
  import { notBundle } from 'vite-plugin-electron/plugin';
7
7
  import { getPackageInfoSync, loadPackageJSON } from 'local-pkg';
8
8
  import { isCI } from 'ci-info';
9
+ export { isCI } from 'ci-info';
9
10
  import Asar from '@electron/asar';
10
11
  import { build } from 'esbuild';
11
- import { spawn } from 'node:child_process';
12
+ import cp from 'node:child_process';
12
13
  import * as babel from '@babel/core';
13
14
  import MagicString from 'magic-string';
14
- import { brotliCompress } from 'node:zlib';
15
- import { createSign, createPrivateKey, createHash, createCipheriv } from 'node:crypto';
15
+ import zlib from 'node:zlib';
16
+ import crypto from 'node:crypto';
16
17
  import { generate } from 'selfsigned';
17
18
 
18
19
  // src/vite.ts
@@ -75,13 +76,13 @@ function getElectronPath() {
75
76
  if (!electronModulePath) {
76
77
  throw new Error("Electron is not installed");
77
78
  }
78
- const pathFile = path2.join(electronModulePath, "path.txt");
79
+ const pathFile = path5.join(electronModulePath, "path.txt");
79
80
  let executablePath;
80
- if (fs.existsSync(pathFile)) {
81
- executablePath = fs.readFileSync(pathFile, "utf-8");
81
+ if (fs3.existsSync(pathFile)) {
82
+ executablePath = fs3.readFileSync(pathFile, "utf-8");
82
83
  }
83
84
  if (executablePath) {
84
- electronExecPath = path2.join(electronModulePath, "dist", executablePath);
85
+ electronExecPath = path5.join(electronModulePath, "dist", executablePath);
85
86
  process.env.ELECTRON_EXEC_PATH = electronExecPath;
86
87
  } else {
87
88
  throw new Error("Electron executable file is not existed");
@@ -90,23 +91,23 @@ function getElectronPath() {
90
91
  return electronExecPath;
91
92
  }
92
93
  function getBytecodeCompilerPath() {
93
- const scriptPath = path2.join(electronModulePath, "bytenode.cjs");
94
- if (!fs.existsSync(scriptPath)) {
95
- fs.writeFileSync(scriptPath, bytecodeGeneratorScript);
94
+ const scriptPath = path5.join(electronModulePath, "bytenode.cjs");
95
+ if (!fs3.existsSync(scriptPath)) {
96
+ fs3.writeFileSync(scriptPath, bytecodeGeneratorScript);
96
97
  }
97
98
  return scriptPath;
98
99
  }
99
100
  function toRelativePath(filename, importer) {
100
- const relPath = path2.posix.relative(path2.dirname(importer), filename);
101
+ const relPath = path5.posix.relative(path5.dirname(importer), filename);
101
102
  return relPath.startsWith(".") ? relPath : `./${relPath}`;
102
103
  }
103
104
  function compileToBytecode(code) {
104
105
  let data = Buffer.from([]);
105
- const logErr = (...args) => log.error(args.join(" "), { timestamp: true });
106
+ const logErr = (...args) => bytecodeLog.error(args.join(" "), { timestamp: true });
106
107
  const electronPath = getElectronPath();
107
108
  const bytecodePath = getBytecodeCompilerPath();
108
- return new Promise((resolve2, reject) => {
109
- const proc = spawn(electronPath, [bytecodePath], {
109
+ return new Promise((resolve, reject) => {
110
+ const proc = cp.spawn(electronPath, [bytecodePath], {
110
111
  env: { ELECTRON_RUN_AS_NODE: "1" },
111
112
  stdio: ["pipe", "pipe", "pipe", "ipc"]
112
113
  });
@@ -117,7 +118,7 @@ function compileToBytecode(code) {
117
118
  if (proc.stdout) {
118
119
  proc.stdout.on("data", (chunk) => data = Buffer.concat([data, chunk]));
119
120
  proc.stdout.on("error", (err) => logErr(err));
120
- proc.stdout.on("end", () => resolve2(data));
121
+ proc.stdout.on("end", () => resolve(data));
121
122
  }
122
123
  if (proc.stderr) {
123
124
  proc.stderr.on("data", (chunk) => logErr("Error: ", chunk.toString()));
@@ -125,37 +126,77 @@ function compileToBytecode(code) {
125
126
  }
126
127
  proc.addListener("error", (err) => logErr(err));
127
128
  proc.on("error", (err) => reject(err));
128
- proc.on("exit", () => resolve2(data));
129
+ proc.on("exit", () => resolve(data));
129
130
  });
130
131
  }
131
132
  function convertArrowToFunction(code) {
132
133
  const result = babel.transform(code, {
133
- plugins: ["@babel/plugin-transform-arrow-functions"]
134
+ plugins: ["@babel/plugin-transform-arrow-functions", "@babel/plugin-transform-template-literals"]
134
135
  });
135
136
  return {
136
137
  code: result?.code || code,
137
138
  map: result?.map
138
139
  };
139
140
  }
140
- function escapeRegExpString(str) {
141
- return str.replace(/\\/g, "\\\\").replace(/[|{}()[\]^$+*?.]/g, "\\$&");
141
+ var decodeFn = ";function _0xstr_(a,b){return String.fromCharCode.apply(0,a.map(function(x){return x-b}))};";
142
+ function obfuscateString(input, offset = ~~(Math.random() * 16) + 1) {
143
+ const hexArray = input.split("").map((c) => "0x" + (c.charCodeAt(0) + offset).toString(16));
144
+ return `_0xstr_([${hexArray.join(",")}],${offset})`;
142
145
  }
143
- function convertString(code, strings, sourcemap) {
144
- let s = null;
145
- for (const str of strings.filter(Boolean)) {
146
- const regex = new RegExp(`["']${escapeRegExpString(str)}["']`, "g");
147
- s ||= new MagicString(code).replace(regex, (match) => obfuscateString(match.slice(1, -1)));
146
+ function convertLiteral(code, sourcemap, offset) {
147
+ const s = new MagicString(code);
148
+ let hasTransformed = false;
149
+ const ast = babel.parse(code, { ast: true });
150
+ if (!ast) {
151
+ throw new Error("cannot parse code");
148
152
  }
149
- return s ? {
153
+ babel.traverse(ast, {
154
+ StringLiteral(path6) {
155
+ const parent = path6.parent;
156
+ const node = path6.node;
157
+ if (parent.type === "CallExpression") {
158
+ if (parent.callee.type === "Identifier" && parent.callee.name === "require") {
159
+ return;
160
+ }
161
+ if (parent.callee.type === "Import") {
162
+ return;
163
+ }
164
+ }
165
+ if (parent.type.startsWith("Export")) {
166
+ return;
167
+ }
168
+ if (parent.type.startsWith("Import")) {
169
+ return;
170
+ }
171
+ if (parent.type === "ObjectProperty" && parent.key === node) {
172
+ const result2 = `[${obfuscateString(node.value, offset)}]`;
173
+ const start2 = node.start;
174
+ const end2 = node.end;
175
+ if (start2 && end2) {
176
+ s.overwrite(start2, end2, result2);
177
+ hasTransformed = true;
178
+ }
179
+ return;
180
+ }
181
+ if (!node.value.trim()) {
182
+ return;
183
+ }
184
+ const result = obfuscateString(node.value, offset);
185
+ const start = node.start;
186
+ const end = node.end;
187
+ if (start && end) {
188
+ s.overwrite(start, end, result);
189
+ hasTransformed = true;
190
+ }
191
+ }
192
+ });
193
+ if (hasTransformed) {
194
+ s.append("\n").append(decodeFn);
195
+ }
196
+ return {
150
197
  code: s.toString(),
151
- map: sourcemap ? s.generateMap({ hires: "boundary" }) : null
152
- } : { code };
153
- }
154
- function obfuscateString(input) {
155
- const offset = Math.floor(Math.random() * 2 << 4) + 1;
156
- const hexArray = Array.from(input).map((c) => "0x" + (c.charCodeAt(0) + offset).toString(16));
157
- const decodeFn = `function(a,b){return String.fromCharCode.apply(null,a.map(x=>+x-b))}`;
158
- return `(${decodeFn})([${hexArray.join(",")}],${offset})`;
198
+ map: sourcemap ? s.generateMap({ hires: true }) : void 0
199
+ };
159
200
  }
160
201
 
161
202
  // src/build-plugins/utils.ts
@@ -178,11 +219,11 @@ async function buildAsar({
178
219
  rendererDistPath,
179
220
  generateGzipFile
180
221
  }) {
181
- renameSync(rendererDistPath, join(electronDistPath, "renderer"));
182
- writeFileSync(join(electronDistPath, "version"), version);
222
+ fs3.renameSync(rendererDistPath, path5.join(electronDistPath, "renderer"));
223
+ fs3.writeFileSync(path5.join(electronDistPath, "version"), version);
183
224
  await Asar.createPackage(electronDistPath, asarOutputPath);
184
- const buf = await generateGzipFile(readFileSync(asarOutputPath));
185
- writeFileSync(gzipPath, buf);
225
+ const buf = await generateGzipFile(fs3.readFileSync(asarOutputPath));
226
+ fs3.writeFileSync(gzipPath, buf);
186
227
  log.info(`build update asar to '${gzipPath}' [${readableSize(buf.length)}]`, { timestamp: true });
187
228
  return buf;
188
229
  }
@@ -205,9 +246,9 @@ async function buildVersion({
205
246
  signature: "",
206
247
  version
207
248
  };
208
- if (existsSync(versionPath)) {
249
+ if (fs3.existsSync(versionPath)) {
209
250
  try {
210
- const oldVersionJson = JSON.parse(readFileSync(versionPath, "utf-8"));
251
+ const oldVersionJson = JSON.parse(fs3.readFileSync(versionPath, "utf-8"));
211
252
  if (isUpdateJSON(oldVersionJson)) {
212
253
  _json = oldVersionJson;
213
254
  } else {
@@ -221,7 +262,7 @@ async function buildVersion({
221
262
  if (!isUpdateJSON(_json)) {
222
263
  throw new Error("invalid version info");
223
264
  }
224
- writeFileSync(versionPath, JSON.stringify(_json, null, 2));
265
+ fs3.writeFileSync(versionPath, JSON.stringify(_json, null, 2));
225
266
  log.info(`build version info to '${versionPath}'`, { timestamp: true });
226
267
  }
227
268
  async function buildEntry({
@@ -231,7 +272,7 @@ async function buildEntry({
231
272
  entryOutputDirPath,
232
273
  nativeModuleEntryMap,
233
274
  overrideEsbuildOptions
234
- }, define, protectedStrings) {
275
+ }, define, bytecodeOptions) {
235
276
  const option = mergeConfig(
236
277
  {
237
278
  entryPoints: {
@@ -247,6 +288,7 @@ async function buildEntry({
247
288
  entryNames: "[dir]/[name]",
248
289
  assetNames: "[dir]/[name]",
249
290
  external: ["electron", "original-fs"],
291
+ treeShaking: true,
250
292
  loader: {
251
293
  ".node": "empty"
252
294
  },
@@ -255,13 +297,13 @@ async function buildEntry({
255
297
  overrideEsbuildOptions ?? {}
256
298
  );
257
299
  const { metafile } = await build(option);
258
- if (protectedStrings === void 0) {
300
+ if (!bytecodeOptions || !bytecodeOptions.enable) {
259
301
  return;
260
302
  }
261
303
  const filePaths = Object.keys(metafile?.outputs ?? []);
262
304
  for (const filePath of filePaths) {
263
- let code = readFileSync(filePath, "utf-8");
264
- const fileName = basename(filePath);
305
+ let code = fs3.readFileSync(filePath, "utf-8");
306
+ const fileName = path5.basename(filePath);
265
307
  const isEntry = fileName.endsWith("entry.js");
266
308
  if (isEntry) {
267
309
  code = code.replace(
@@ -269,16 +311,19 @@ async function buildEntry({
269
311
  (_, cert) => `"${cert.slice(1, -1).replace(/\n/g, "\\n")}"`
270
312
  );
271
313
  }
272
- const transformedCode = convertString(
273
- convertArrowToFunction(code).code,
274
- [...protectedStrings, ...isEntry ? getCert(code) : []]
275
- ).code;
314
+ let transformedCode = convertLiteral(convertArrowToFunction(code).code).code;
315
+ if (bytecodeOptions.beforeCompile) {
316
+ const result = await bytecodeOptions.beforeCompile(transformedCode, filePath);
317
+ if (result) {
318
+ transformedCode = result;
319
+ }
320
+ }
276
321
  const buffer = await compileToBytecode(transformedCode);
277
- writeFileSync(`${filePath}c`, buffer);
278
- writeFileSync(
322
+ fs3.writeFileSync(
279
323
  filePath,
280
324
  `${isEntry ? bytecodeModuleLoaderCode : useStrict}${isEntry ? "" : "module.exports = "}require("./${fileName}c")`
281
325
  );
326
+ fs3.writeFileSync(`${filePath}c`, buffer);
282
327
  bytecodeLog.info(
283
328
  `${filePath} [${(buffer.byteLength / 1e3).toFixed(2)} kB]`,
284
329
  { timestamp: true }
@@ -286,49 +331,45 @@ async function buildEntry({
286
331
  }
287
332
  bytecodeLog.info(`${filePaths.length} file${filePaths.length > 1 ? "s" : ""} compiled into bytecode`, { timestamp: true });
288
333
  }
289
- function getCert(code) {
290
- const cert = code.match(/-----BEGIN CERTIFICATE-----[\s\S]*-----END CERTIFICATE-----\\n/)?.[0];
291
- return cert ? [cert] : [];
292
- }
293
334
  async function defaultZipFile(buffer) {
294
- return new Promise((resolve2, reject) => {
295
- brotliCompress(buffer, (err, buffer2) => {
335
+ return new Promise((resolve, reject) => {
336
+ zlib.brotliCompress(buffer, (err, buffer2) => {
296
337
  if (err) {
297
338
  reject(err);
298
339
  } else {
299
- resolve2(buffer2);
340
+ resolve(buffer2);
300
341
  }
301
342
  });
302
343
  });
303
344
  }
304
345
  function hashBuffer(data, length) {
305
- const hash = createHash("SHA256").update(data).digest("binary");
346
+ const hash = crypto.createHash("SHA256").update(data).digest("binary");
306
347
  return Buffer.from(hash).subarray(0, length);
307
348
  }
308
349
  function aesEncrypt(plainText, key, iv) {
309
- const cipher = createCipheriv("aes-256-cbc", key, iv);
350
+ const cipher = crypto.createCipheriv("aes-256-cbc", key, iv);
310
351
  return cipher.update(plainText, "utf8", "base64url") + cipher.final("base64url");
311
352
  }
312
353
  function defaultSignature(buffer, privateKey, cert, version) {
313
- const sig = createSign("RSA-SHA256").update(buffer).sign(createPrivateKey(privateKey), "base64");
354
+ const sig = crypto.createSign("RSA-SHA256").update(buffer).sign(crypto.createPrivateKey(privateKey), "base64");
314
355
  return aesEncrypt(`${sig}%${version}`, hashBuffer(cert, 32), hashBuffer(buffer, 16));
315
356
  }
316
357
  function generateKeyPair(keyLength, subject, days, privateKeyPath, certPath) {
317
- const privateKeyDir = dirname(privateKeyPath);
318
- if (!existsSync(privateKeyDir)) {
319
- mkdirSync(privateKeyDir, { recursive: true });
358
+ const privateKeyDir = path5.dirname(privateKeyPath);
359
+ if (!fs3.existsSync(privateKeyDir)) {
360
+ fs3.mkdirSync(privateKeyDir, { recursive: true });
320
361
  }
321
- const certDir = dirname(certPath);
322
- if (!existsSync(certDir)) {
323
- mkdirSync(certDir, { recursive: true });
362
+ const certDir = path5.dirname(certPath);
363
+ if (!fs3.existsSync(certDir)) {
364
+ fs3.mkdirSync(certDir, { recursive: true });
324
365
  }
325
366
  const { cert, private: privateKey } = generate(subject, {
326
367
  keySize: keyLength,
327
368
  algorithm: "sha256",
328
369
  days
329
370
  });
330
- writeFileSync(privateKeyPath, privateKey.replace(/\r\n?/g, "\n"));
331
- writeFileSync(certPath, cert.replace(/\r\n?/g, "\n"));
371
+ fs3.writeFileSync(privateKeyPath, privateKey.replace(/\r\n?/g, "\n"));
372
+ fs3.writeFileSync(certPath, cert.replace(/\r\n?/g, "\n"));
332
373
  }
333
374
  function parseKeys({
334
375
  keyLength,
@@ -337,22 +378,22 @@ function parseKeys({
337
378
  subject,
338
379
  days
339
380
  }) {
340
- const keysDir = dirname(privateKeyPath);
381
+ const keysDir = path5.dirname(privateKeyPath);
341
382
  let privateKey = process.env.UPDATER_PK;
342
383
  let cert = process.env.UPDATER_CERT;
343
384
  if (privateKey && cert) {
344
385
  log.info("use UPDATER_PK and UPDATER_CERT from environment variables", { timestamp: true });
345
386
  return { privateKey, cert };
346
387
  }
347
- if (!existsSync(keysDir)) {
348
- mkdirSync(keysDir);
388
+ if (!fs3.existsSync(keysDir)) {
389
+ fs3.mkdirSync(keysDir);
349
390
  }
350
- if (!existsSync(privateKeyPath) || !existsSync(certPath)) {
391
+ if (!fs3.existsSync(privateKeyPath) || !fs3.existsSync(certPath)) {
351
392
  log.info("no key pair found, generate new key pair", { timestamp: true });
352
393
  generateKeyPair(keyLength, parseSubjects(subject), days, privateKeyPath, certPath);
353
394
  }
354
- privateKey = readFileSync(privateKeyPath, "utf-8");
355
- cert = readFileSync(certPath, "utf-8");
395
+ privateKey = fs3.readFileSync(privateKeyPath, "utf-8");
396
+ cert = fs3.readFileSync(certPath, "utf-8");
356
397
  return { privateKey, cert };
357
398
  }
358
399
  function parseSubjects(subject) {
@@ -431,15 +472,16 @@ function parseOptions(pkg, sourcemap = false, minify = false, options = {}) {
431
472
  };
432
473
  return { buildAsarOption, buildEntryOption, buildVersionOption, postBuild, cert };
433
474
  }
434
- function bytecodePlugin(isBuild, env, options = {}) {
435
- if (!isBuild) {
436
- return null;
437
- }
475
+ function bytecodePlugin(env, options) {
438
476
  const {
439
- protectedStrings = [],
440
- enablePreload = false
477
+ enable,
478
+ preload = false,
479
+ beforeCompile
441
480
  } = options;
442
- if (!enablePreload && env === "preload") {
481
+ if (!enable) {
482
+ return null;
483
+ }
484
+ if (!preload && env === "preload") {
443
485
  bytecodeLog.warn('bytecodePlugin is skiped in preload. To enable in preload, please manually set the "enablePreload" option to true and set `sandbox: false` when creating the window', { timestamp: true });
444
486
  return null;
445
487
  }
@@ -455,10 +497,9 @@ function bytecodePlugin(isBuild, env, options = {}) {
455
497
  config = resolvedConfig;
456
498
  },
457
499
  transform(code, id2) {
458
- if (protectedStrings.length === 0 || !filter(id2)) {
459
- return;
500
+ if (!filter(id2)) {
501
+ return convertLiteral(code, !!config.build.sourcemap);
460
502
  }
461
- return convertString(code, protectedStrings, !!config.build.sourcemap);
462
503
  },
463
504
  generateBundle(options2) {
464
505
  if (options2.format !== "es" && bytecodeRequired) {
@@ -495,7 +536,7 @@ function bytecodePlugin(isBuild, env, options = {}) {
495
536
  (chunk) => chunk.type === "chunk" && chunk.fileName !== bytecodeModuleLoader
496
537
  );
497
538
  const bytecodeChunks = chunks.map((chunk) => chunk.fileName);
498
- const nonEntryChunks = chunks.filter((chunk) => !chunk.isEntry).map((chunk) => path2.basename(chunk.fileName));
539
+ const nonEntryChunks = chunks.filter((chunk) => !chunk.isEntry).map((chunk) => path5.basename(chunk.fileName));
499
540
  const pattern = nonEntryChunks.map((chunk) => `(${chunk})`).join("|");
500
541
  const bytecodeRE = pattern ? new RegExp(`require\\(\\S*(?=(${pattern})\\S*\\))`, "g") : null;
501
542
  const getBytecodeLoaderBlock = (chunkFileName) => {
@@ -506,6 +547,12 @@ function bytecodePlugin(isBuild, env, options = {}) {
506
547
  const chunk = output[name];
507
548
  if (chunk.type === "chunk") {
508
549
  let _code = chunk.code;
550
+ if (beforeCompile) {
551
+ const cbResult = await beforeCompile(_code, chunk.fileName);
552
+ if (cbResult) {
553
+ _code = cbResult;
554
+ }
555
+ }
509
556
  if (bytecodeRE && _code.match(bytecodeRE)) {
510
557
  let match;
511
558
  const s = new MagicString(_code);
@@ -518,20 +565,20 @@ function bytecodePlugin(isBuild, env, options = {}) {
518
565
  }
519
566
  _code = s.toString();
520
567
  }
521
- const chunkFilePath = path2.resolve(outDir, name);
568
+ const chunkFilePath = path5.resolve(outDir, name);
522
569
  if (bytecodeChunks.includes(name)) {
523
570
  const bytecodeBuffer = await compileToBytecode(_code);
524
- fs.writeFileSync(path2.resolve(outDir, name + "c"), bytecodeBuffer);
571
+ fs3.writeFileSync(chunkFilePath + "c", bytecodeBuffer);
525
572
  if (chunk.isEntry) {
526
573
  const bytecodeLoaderBlock = getBytecodeLoaderBlock(chunk.fileName);
527
- const bytecodeModuleBlock = `require("./${path2.basename(name) + "c"}");`;
574
+ const bytecodeModuleBlock = `require("./${path5.basename(name) + "c"}");`;
528
575
  const code = `${useStrict}
529
576
  ${bytecodeLoaderBlock}
530
577
  module.exports=${bytecodeModuleBlock}
531
578
  `;
532
- fs.writeFileSync(chunkFilePath, code);
579
+ fs3.writeFileSync(chunkFilePath, code);
533
580
  } else {
534
- fs.unlinkSync(chunkFilePath);
581
+ fs3.unlinkSync(chunkFilePath);
535
582
  }
536
583
  bytecodeFiles.push({ name: name + "c", size: bytecodeBuffer.length });
537
584
  } else {
@@ -558,14 +605,14 @@ module.exports=${bytecodeModuleBlock}
558
605
  _code = hasBytecodeMoudle ? _code.replace(useStrict, `${useStrict}
559
606
  ${bytecodeLoaderBlock}`) : _code;
560
607
  }
561
- fs.writeFileSync(chunkFilePath, _code);
608
+ fs3.writeFileSync(chunkFilePath, _code);
562
609
  }
563
610
  }
564
611
  })
565
612
  );
566
613
  },
567
614
  closeBundle() {
568
- const outDir = `${normalizePath(path2.relative(config.root, path2.resolve(config.root, config.build.outDir)))}/`;
615
+ const outDir = `${normalizePath(path5.relative(config.root, path5.resolve(config.root, config.build.outDir)))}/`;
569
616
  bytecodeFiles.forEach((file) => {
570
617
  bytecodeLog.info(
571
618
  `${outDir}${file.name} [${readableSize(file.size)}]`,
@@ -577,8 +624,6 @@ ${bytecodeLoaderBlock}`) : _code;
577
624
  }
578
625
  };
579
626
  }
580
-
581
- // src/vite.ts
582
627
  function debugStartup(args) {
583
628
  if (process.env.VSCODE_DEBUG) {
584
629
  console.log("[startup] Electron App");
@@ -589,9 +634,9 @@ function debugStartup(args) {
589
634
  function getMainFilePath(options) {
590
635
  let mainFilePath;
591
636
  if (typeof options === "string") {
592
- mainFilePath = basename(options);
637
+ mainFilePath = path5.basename(options);
593
638
  } else if (Array.isArray(options)) {
594
- mainFilePath = basename(options[0]);
639
+ mainFilePath = path5.basename(options[0]);
595
640
  } else {
596
641
  const name = options?.index ?? options?.main;
597
642
  if (!name) {
@@ -616,7 +661,7 @@ async function electronWithUpdater(options) {
616
661
  preload: _preload,
617
662
  sourcemap = !isBuild,
618
663
  minify = isBuild,
619
- buildVersionJson = isCI,
664
+ buildVersionJson,
620
665
  updater,
621
666
  bytecode,
622
667
  useNotBundle = true,
@@ -631,21 +676,18 @@ async function electronWithUpdater(options) {
631
676
  return void 0;
632
677
  }
633
678
  const _options = parseOptions(pkg, sourcemap, minify, updater);
634
- const bytecodeOptions = typeof bytecode === "object" ? bytecode : bytecode === true ? { protectedStrings: [] } : void 0;
635
- if (bytecodeOptions) {
636
- minify = false;
637
- }
679
+ const bytecodeOptions = typeof bytecode === "object" ? bytecode : bytecode === true ? { enable: true } : void 0;
638
680
  try {
639
- rmSync(_options.buildAsarOption.electronDistPath, { recursive: true, force: true });
640
- rmSync(_options.buildEntryOption.entryOutputDirPath, { recursive: true, force: true });
681
+ fs3.rmSync(_options.buildAsarOption.electronDistPath, { recursive: true, force: true });
682
+ fs3.rmSync(_options.buildEntryOption.entryOutputDirPath, { recursive: true, force: true });
641
683
  } catch {
642
684
  }
643
685
  log.info(`remove old files`, { timestamp: true });
644
686
  const { buildAsarOption, buildEntryOption, buildVersionOption, postBuild, cert } = _options;
645
687
  const { entryOutputDirPath, nativeModuleEntryMap, appEntryPath } = buildEntryOption;
646
688
  sourcemap ??= isBuild || !!process.env.VSCODE_DEBUG;
647
- const _appPath = normalizePath(join(entryOutputDirPath, "entry.js"));
648
- if (resolve(normalizePath(pkg.main)) !== resolve(_appPath)) {
689
+ const _appPath = normalizePath(path5.join(entryOutputDirPath, "entry.js"));
690
+ if (path5.resolve(normalizePath(pkg.main)) !== path5.resolve(_appPath)) {
649
691
  throw new Error(`wrong "main" field in package.json: "${pkg.main}", it should be "${_appPath}"`);
650
692
  }
651
693
  const define = {
@@ -661,20 +703,20 @@ async function electronWithUpdater(options) {
661
703
  await buildEntry(
662
704
  buildEntryOption,
663
705
  define,
664
- isBuild ? bytecodeOptions?.protectedStrings : void 0
706
+ bytecodeOptions
665
707
  );
666
708
  log.info(`vite build entry to '${entryOutputDirPath}'`, { timestamp: true });
667
709
  };
668
710
  const _postBuild = postBuild ? async () => await postBuild({
669
711
  getPathFromEntryOutputDir(...paths) {
670
- return join(entryOutputDirPath, ...paths);
712
+ return path5.join(entryOutputDirPath, ...paths);
671
713
  },
672
714
  copyToEntryOutputDir({ from, to, skipIfExist = true }) {
673
- if (existsSync(from)) {
674
- const target = join(entryOutputDirPath, to ?? basename(from));
675
- if (!skipIfExist || !existsSync(target)) {
715
+ if (fs3.existsSync(from)) {
716
+ const target = path5.join(entryOutputDirPath, to ?? path5.basename(from));
717
+ if (!skipIfExist || !fs3.existsSync(target)) {
676
718
  try {
677
- cpSync(from, target);
719
+ fs3.cpSync(from, target);
678
720
  } catch (error) {
679
721
  log.warn(`copy failed: ${error}`);
680
722
  }
@@ -685,7 +727,8 @@ async function electronWithUpdater(options) {
685
727
  };
686
728
  let isInit = false;
687
729
  const rollupOptions = {
688
- external: (src) => src.startsWith("node:") || Object.keys("dependencies" in pkg ? pkg.dependencies : {}).includes(src)
730
+ external: (src) => src.startsWith("node:") || Object.keys("dependencies" in pkg ? pkg.dependencies : {}).includes(src) || src === "original-fs",
731
+ treeshake: true
689
732
  };
690
733
  const electronPluginOptions = {
691
734
  main: {
@@ -706,7 +749,7 @@ async function electronWithUpdater(options) {
706
749
  {
707
750
  plugins: [
708
751
  !isBuild && useNotBundle ? notBundle() : void 0,
709
- bytecodeOptions && bytecodePlugin(isBuild, "main", bytecodeOptions)
752
+ bytecodeOptions && bytecodePlugin("main", bytecodeOptions)
710
753
  ],
711
754
  build: {
712
755
  sourcemap,
@@ -725,7 +768,7 @@ async function electronWithUpdater(options) {
725
768
  vite: mergeConfig(
726
769
  {
727
770
  plugins: [
728
- bytecodeOptions && bytecodePlugin(isBuild, "preload", bytecodeOptions),
771
+ bytecodeOptions && bytecodePlugin("preload", bytecodeOptions),
729
772
  {
730
773
  name: `${id}-build`,
731
774
  enforce: "post",
@@ -736,7 +779,9 @@ async function electronWithUpdater(options) {
736
779
  await _buildEntry();
737
780
  await _postBuild();
738
781
  const buffer = await buildAsar(buildAsarOption);
739
- if (buildVersionJson) {
782
+ if (!buildVersionJson && !isCI) {
783
+ log.warn("no `buildVersionJson` setup, skip build version json. Will build in CI by default", { timestamp: true });
784
+ } else {
740
785
  await buildVersion(buildVersionOption, buffer);
741
786
  }
742
787
  }
@@ -769,7 +814,10 @@ async function electronWithUpdater(options) {
769
814
  }
770
815
  let extraHmrPlugin;
771
816
  if (nativeModuleEntryMap) {
772
- const files = [...Object.values(nativeModuleEntryMap), appEntryPath].map((file) => resolve(normalizePath(file)));
817
+ const files = [
818
+ ...Object.values(nativeModuleEntryMap),
819
+ appEntryPath
820
+ ].map((file) => path5.resolve(normalizePath(file)));
773
821
  extraHmrPlugin = {
774
822
  name: `${id}-dev`,
775
823
  apply() {
@@ -0,0 +1,10 @@
1
+ declare function hashBuffer(data: string | Buffer, length: number): Buffer;
2
+ declare function aesEncrypt(plainText: string, key: Buffer, iv: Buffer): string;
3
+ declare function defaultSignature(buffer: Buffer, privateKey: string, cert: string, version: string): string;
4
+ declare function aesDecrypt(encryptedText: string, key: Buffer, iv: Buffer): string;
5
+ declare function defaultVerifySignature(buffer: Buffer, version: string, signature: string, cert: string): boolean;
6
+
7
+ declare function defaultZipFile(buffer: Buffer): Promise<Buffer>;
8
+ declare function defaultUnzipFile(buffer: Buffer): Promise<Buffer>;
9
+
10
+ export { defaultUnzipFile as a, aesEncrypt as b, defaultSignature as c, defaultZipFile as d, aesDecrypt as e, defaultVerifySignature as f, hashBuffer as h };
@@ -0,0 +1,10 @@
1
+ declare function hashBuffer(data: string | Buffer, length: number): Buffer;
2
+ declare function aesEncrypt(plainText: string, key: Buffer, iv: Buffer): string;
3
+ declare function defaultSignature(buffer: Buffer, privateKey: string, cert: string, version: string): string;
4
+ declare function aesDecrypt(encryptedText: string, key: Buffer, iv: Buffer): string;
5
+ declare function defaultVerifySignature(buffer: Buffer, version: string, signature: string, cert: string): boolean;
6
+
7
+ declare function defaultZipFile(buffer: Buffer): Promise<Buffer>;
8
+ declare function defaultUnzipFile(buffer: Buffer): Promise<Buffer>;
9
+
10
+ export { defaultUnzipFile as a, aesEncrypt as b, defaultSignature as c, defaultZipFile as d, aesDecrypt as e, defaultVerifySignature as f, hashBuffer as h };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "electron-incremental-update",
3
3
  "type": "module",
4
- "version": "2.0.0-beta.6",
4
+ "version": "2.0.0-beta.8",
5
5
  "description": "electron incremental update tools, powered by vite",
6
6
  "author": "subframe7536",
7
7
  "license": "MIT",
@@ -45,6 +45,7 @@
45
45
  "build": "tsup && esno fix-module.cjs",
46
46
  "release": "pnpm test && pnpm run build && bumpp --all && npm publish",
47
47
  "test": "vitest --run",
48
+ "test:dev": "vitest",
48
49
  "format": "eslint . --fix"
49
50
  },
50
51
  "publishConfig": {
@@ -53,27 +54,28 @@
53
54
  },
54
55
  "peerDependencies": {
55
56
  "@electron/asar": "*",
56
- "esbuild": "*",
57
- "magic-string": "*"
57
+ "esbuild": "*"
58
58
  },
59
59
  "dependencies": {
60
- "@babel/core": "^7.24.7",
60
+ "@babel/core": "^7.24.9",
61
61
  "@babel/plugin-transform-arrow-functions": "^7.24.7",
62
+ "@babel/plugin-transform-template-literals": "^7.24.7",
62
63
  "@subframe7536/type-utils": "^0.1.6",
63
64
  "ci-info": "^4.0.0",
64
65
  "local-pkg": "^0.5.0",
66
+ "magic-string": "^0.30.10",
65
67
  "selfsigned": "^2.4.1",
66
68
  "vite-plugin-electron": "^0.28.7"
67
69
  },
68
70
  "devDependencies": {
69
- "@subframe7536/eslint-config": "^0.7.2",
71
+ "@subframe7536/eslint-config": "^0.7.3",
70
72
  "@types/babel__core": "^7.20.5",
71
73
  "@types/node": "^20.14.11",
72
74
  "bumpp": "^9.4.1",
73
75
  "electron": "28.2.10",
74
76
  "eslint": "^9.7.0",
75
77
  "esno": "^4.7.0",
76
- "tsup": "^8.1.0",
78
+ "tsup": "^8.2.1",
77
79
  "typescript": "^5.5.3",
78
80
  "vite": "^5.3.4",
79
81
  "vite-plugin-electron": "^0.28.7",