esp32tool 1.6.3 → 1.6.4

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/js/script.js CHANGED
@@ -199,6 +199,7 @@ const butReadFlash = document.getElementById("butReadFlash");
199
199
  const readOffset = document.getElementById("readOffset");
200
200
  const readSize = document.getElementById("readSize");
201
201
  const readProgress = document.getElementById("readProgress");
202
+ const eraseProgress = document.getElementById("eraseProgress");
202
203
  const butReadPartitions = document.getElementById("butReadPartitions");
203
204
  const butDetectFS = document.getElementById("butDetectFS");
204
205
  const butOpenFSManager = document.getElementById("butOpenFSManager");
@@ -1601,6 +1602,7 @@ async function clickErase() {
1601
1602
  baudRateSelect.disabled = true;
1602
1603
  butErase.disabled = true;
1603
1604
  butProgram.disabled = true;
1605
+ eraseProgress.classList.remove("hidden");
1604
1606
  try {
1605
1607
  logMsg("Erasing flash memory. Please wait...");
1606
1608
  let stamp = Date.now();
@@ -1609,6 +1611,7 @@ async function clickErase() {
1609
1611
  } catch (e) {
1610
1612
  errorMsg(e);
1611
1613
  } finally {
1614
+ eraseProgress.classList.add("hidden");
1612
1615
  butErase.disabled = false;
1613
1616
  baudRateSelect.disabled = false;
1614
1617
  butProgram.disabled = getValidFiles().length == 0;
@@ -10,6 +10,8 @@ export class ColoredConsole {
10
10
  backgroundColor: null,
11
11
  carriageReturn: false,
12
12
  secret: false,
13
+ blink: false,
14
+ rapidBlink: false,
13
15
  };
14
16
  }
15
17
 
@@ -49,6 +51,8 @@ export class ColoredConsole {
49
51
  if (this.state.underline) span.classList.add("log-underline");
50
52
  if (this.state.strikethrough) span.classList.add("log-strikethrough");
51
53
  if (this.state.secret) span.classList.add("log-secret");
54
+ if (this.state.blink) span.classList.add("log-blink");
55
+ if (this.state.rapidBlink) span.classList.add("log-rapid-blink");
52
56
  if (this.state.foregroundColor !== null)
53
57
  span.classList.add(`log-fg-${this.state.foregroundColor}`);
54
58
  if (this.state.backgroundColor !== null)
@@ -85,6 +89,8 @@ export class ColoredConsole {
85
89
  this.state.foregroundColor = null;
86
90
  this.state.backgroundColor = null;
87
91
  this.state.secret = false;
92
+ this.state.blink = false;
93
+ this.state.rapidBlink = false;
88
94
  break;
89
95
  case 1:
90
96
  this.state.bold = true;
@@ -96,10 +102,13 @@ export class ColoredConsole {
96
102
  this.state.underline = true;
97
103
  break;
98
104
  case 5:
99
- this.state.secret = true;
105
+ this.state.blink = true;
100
106
  break;
101
107
  case 6:
102
- this.state.secret = false;
108
+ this.state.rapidBlink = true;
109
+ break;
110
+ case 8:
111
+ this.state.secret = true;
103
112
  break;
104
113
  case 9:
105
114
  this.state.strikethrough = true;
@@ -113,6 +122,13 @@ export class ColoredConsole {
113
122
  case 24:
114
123
  this.state.underline = false;
115
124
  break;
125
+ case 25:
126
+ this.state.blink = false;
127
+ this.state.rapidBlink = false;
128
+ break;
129
+ case 28:
130
+ this.state.secret = false;
131
+ break;
116
132
  case 29:
117
133
  this.state.strikethrough = false;
118
134
  break;
@@ -232,6 +248,17 @@ export const coloredConsoleStyles = `
232
248
  width: 1px;
233
249
  font-size: 1px;
234
250
  }
251
+ .log-blink {
252
+ animation: blink 1s step-start infinite;
253
+ }
254
+ .log-rapid-blink {
255
+ animation: blink 0.3s step-start infinite;
256
+ }
257
+ @keyframes blink {
258
+ 50% {
259
+ opacity: 0;
260
+ }
261
+ }
235
262
  .log-fg-black {
236
263
  color: rgb(128, 128, 128);
237
264
  }
package/package.cli.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "esp32tool",
3
- "version": "1.3.2",
3
+ "version": "1.6.3",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "description": "ESP32Tool - Standalone command-line tool (build-time config only)",
@@ -20,7 +20,7 @@
20
20
  "dependencies": {
21
21
  "pako": "^2.1.0",
22
22
  "tslib": "^2.8.1",
23
- "usb": "^2.16.0"
23
+ "usb": "^2.17.0"
24
24
  },
25
25
  "devDependencies": {
26
26
  "electron": "^39.2.5"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "esp32tool",
3
- "version": "1.6.3",
3
+ "version": "1.6.4",
4
4
  "type": "module",
5
5
  "description": "Flash & Read ESP devices using WebSerial, Electron, and also Android mobile via WebUSB",
6
6
  "main": "electron/main.cjs",
@@ -17,7 +17,7 @@
17
17
  "author": "Johann Obermeier",
18
18
  "license": "MIT",
19
19
  "engines": {
20
- "node": ">=22.12.0"
20
+ "node": ">=25.4.0"
21
21
  },
22
22
  "scripts": {
23
23
  "prebuild": "node -e \"const fs=require('fs'); fs.rmSync('dist',{recursive:true,force:true}); fs.rmSync('js/modules',{recursive:true,force:true}); fs.mkdirSync('js/modules',{recursive:true});\"",
@@ -48,28 +48,28 @@
48
48
  "@electron-forge/maker-squirrel": "^7.11.1",
49
49
  "@electron-forge/maker-zip": "^7.11.1",
50
50
  "@electron-forge/plugin-auto-unpack-natives": "^7.11.1",
51
- "@electron/fuses": "^2.0.0",
51
+ "@electron/fuses": "^2.1.1",
52
52
  "@eslint/js": "^9.39.3",
53
53
  "@rollup/plugin-json": "^6.1.0",
54
54
  "@rollup/plugin-node-resolve": "^16.0.0",
55
- "@rollup/plugin-terser": "^0.4.4",
55
+ "@rollup/plugin-terser": "^1.0.0",
56
56
  "@rollup/plugin-typescript": "^12.3.0",
57
- "@types/node": "^25.3.0",
57
+ "@types/node": "^25.4.0",
58
58
  "@types/pako": "^2.0.4",
59
59
  "@types/serialport": "^10.2.0",
60
60
  "@types/w3c-web-serial": "^1.0.7",
61
61
  "archiver": "^7.0.1",
62
- "electron": "^40.6.0",
62
+ "electron": "^41.1.0",
63
63
  "electron-squirrel-startup": "^1.0.1",
64
64
  "eslint": "^10.0.2",
65
65
  "eslint-config-prettier": "^10.1.8",
66
66
  "eslint-plugin-prettier": "^5.5.5",
67
67
  "npm-run-all": "^4.1.5",
68
68
  "prettier": "^3.8.1",
69
- "rollup": "^4.59.0",
70
- "serve": "^14.2.5",
71
- "typescript": "^5.7.3",
72
- "typescript-eslint": "^8.56.1"
69
+ "rollup": "^4.60.1",
70
+ "serve": "^14.2.6",
71
+ "typescript": "^5.9.3",
72
+ "typescript-eslint": "^8.57.2"
73
73
  },
74
74
  "dependencies": {
75
75
  "pako": "^2.1.0",
@@ -83,6 +83,10 @@
83
83
  "serve": {
84
84
  "ajv": "^8.18.0"
85
85
  },
86
- "@electron/asar": "^4.0.1"
86
+ "@electron/asar": "^4.0.1",
87
+ "serialize-javascript": "^7.0.3",
88
+ "@tootallnate/once": "^3.0.1",
89
+ "http-proxy-agent": "^7.0.2",
90
+ "make-fetch-happen": "^13.0.1"
87
91
  }
88
92
  }
Binary file
Binary file
package/src/cli.ts CHANGED
@@ -399,8 +399,19 @@ async function cmdEraseFlash(esploader: ESPLoader) {
399
399
  // Use stub for erasing
400
400
  const stub = await esploader.runStub();
401
401
 
402
- // Erase flash
403
- await stub.eraseFlash();
402
+ // Show animated progress while erasing
403
+ const frames = ["|", "/", "-", "\\"];
404
+ let frameIdx = 0;
405
+ const spinner = setInterval(() => {
406
+ process.stdout.write(`\rErasing... ${frames[frameIdx++ % frames.length]}`);
407
+ }, 200);
408
+
409
+ try {
410
+ await stub.eraseFlash();
411
+ } finally {
412
+ clearInterval(spinner);
413
+ process.stdout.write("\r \r");
414
+ }
404
415
 
405
416
  cliLogger.log("Erase complete!");
406
417
  }
package/src/esp_loader.ts CHANGED
@@ -4335,6 +4335,8 @@ export class ESPLoader extends EventTarget {
4335
4335
  // Flush serial buffers before flash read operation
4336
4336
  await this.flushSerialBuffers();
4337
4337
 
4338
+ const readStartTime = Date.now();
4339
+
4338
4340
  this.logger.log(
4339
4341
  `Reading ${size} bytes from flash at address 0x${addr.toString(16)}...`,
4340
4342
  );
@@ -4442,6 +4444,8 @@ export class ESPLoader extends EventTarget {
4442
4444
  maxInFlight,
4443
4445
  );
4444
4446
 
4447
+ const chunkStartTime = Date.now();
4448
+
4445
4449
  const [res] = await this.checkCommand(ESP_READ_FLASH, pkt);
4446
4450
 
4447
4451
  if (res != 0) {
@@ -4520,6 +4524,16 @@ export class ESPLoader extends EventTarget {
4520
4524
 
4521
4525
  chunkSuccess = true;
4522
4526
 
4527
+ const chunkDuration = Date.now() - chunkStartTime;
4528
+ const speedKBs = (
4529
+ resp.length /
4530
+ 1024 /
4531
+ (chunkDuration / 1000)
4532
+ ).toFixed(1);
4533
+ this.logger.debug(
4534
+ `Chunk read took ${chunkDuration} ms (${resp.length} bytes, ${speedKBs} KB/s)`,
4535
+ );
4536
+
4523
4537
  // ADAPTIVE SPEED ADJUSTMENT: Only for CDC devices
4524
4538
  // Non-CDC devices (CH340, CP2102) stay at fixed blockSize=31, maxInFlight=31
4525
4539
  if (this.isWebUSB() && this._isCDCDevice && retryCount === 0) {
@@ -4666,6 +4680,16 @@ export class ESPLoader extends EventTarget {
4666
4680
  );
4667
4681
  }
4668
4682
 
4683
+ const totalDuration = Date.now() - readStartTime;
4684
+ const totalSpeedKBs = (
4685
+ allData.length /
4686
+ 1024 /
4687
+ (totalDuration / 1000)
4688
+ ).toFixed(1);
4689
+ this.logger.log(
4690
+ `Read complete: ${allData.length} bytes in ${(totalDuration / 1000).toFixed(1)} s (${totalSpeedKBs} KB/s)`,
4691
+ );
4692
+
4669
4693
  return allData;
4670
4694
  }
4671
4695
  }
package/sw.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // Service Worker for ESP32Tool PWA
2
- const CACHE_NAME = 'esp32tool-v1.6.3';
2
+ const CACHE_NAME = 'esp32tool-v1.6.4';
3
3
  const RUNTIME_CACHE = 'esp32tool-runtime';
4
4
 
5
5
  // Core files to cache on install (relative paths work for any deployment path)