esp32tool 1.6.3 → 1.6.5

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;
@@ -1,194 +1,235 @@
1
1
  export class ColoredConsole {
2
- constructor(targetElement) {
3
- this.targetElement = targetElement;
4
- this.state = {
5
- bold: false,
6
- italic: false,
7
- underline: false,
8
- strikethrough: false,
9
- foregroundColor: null,
10
- backgroundColor: null,
11
- carriageReturn: false,
12
- secret: false,
13
- };
14
- }
15
-
16
- logs() {
17
- return this.targetElement.innerText;
18
- }
19
-
20
- addLine(line) {
21
- // biome-ignore lint/suspicious/noControlCharactersInRegex: ANSI escape sequences
22
- const re = /(?:\x1B|\\x1B)(?:\[(.*?)[@-~]|\].*?(?:\x07|\x1B\\))/g;
23
- let i = 0;
24
-
25
- if (this.state.carriageReturn) {
26
- if (line !== "\n") {
27
- // don't remove if \r\n
28
- if (this.targetElement.lastChild) {
29
- this.targetElement.removeChild(this.targetElement.lastChild);
2
+ constructor(targetElement) {
3
+ this.targetElement = targetElement;
4
+ this.state = {
5
+ bold: false,
6
+ italic: false,
7
+ underline: false,
8
+ strikethrough: false,
9
+ foregroundColor: null,
10
+ backgroundColor: null,
11
+ carriageReturn: false,
12
+ lines: [],
13
+ secret: false,
14
+ blink: false,
15
+ rapidBlink: false,
16
+ };
17
+ }
18
+ logs() {
19
+ if (this.state.lines.length > 0) {
20
+ this.processLines();
30
21
  }
31
- }
32
- this.state.carriageReturn = false;
22
+ return this.targetElement.innerText;
33
23
  }
34
-
35
- if (line.includes("\r")) {
36
- this.state.carriageReturn = true;
24
+ processLine(line) {
25
+ // biome-ignore lint/suspicious/noControlCharactersInRegex: ANSI escape sequences
26
+ // eslint-disable-next-line no-control-regex
27
+ const re = /(?:\x1B|\\x1B)(?:\[(.*?)[@-~]|\].*?(?:\x07|\x1B\\))/g;
28
+ let i = 0;
29
+ const lineSpan = document.createElement("span");
30
+ lineSpan.classList.add("line");
31
+ const addSpan = (content) => {
32
+ if (content === "")
33
+ return;
34
+ const span = document.createElement("span");
35
+ if (this.state.bold)
36
+ span.classList.add("log-bold");
37
+ if (this.state.italic)
38
+ span.classList.add("log-italic");
39
+ if (this.state.underline)
40
+ span.classList.add("log-underline");
41
+ if (this.state.strikethrough)
42
+ span.classList.add("log-strikethrough");
43
+ if (this.state.secret)
44
+ span.classList.add("log-secret");
45
+ if (this.state.blink)
46
+ span.classList.add("log-blink");
47
+ if (this.state.rapidBlink)
48
+ span.classList.add("log-rapid-blink");
49
+ if (this.state.foregroundColor !== null)
50
+ span.classList.add(`log-fg-${this.state.foregroundColor}`);
51
+ if (this.state.backgroundColor !== null)
52
+ span.classList.add(`log-bg-${this.state.backgroundColor}`);
53
+ span.appendChild(document.createTextNode(content));
54
+ lineSpan.appendChild(span);
55
+ if (this.state.secret) {
56
+ const redacted = document.createElement("span");
57
+ redacted.classList.add("log-secret-redacted");
58
+ redacted.appendChild(document.createTextNode("[redacted]"));
59
+ lineSpan.appendChild(redacted);
60
+ }
61
+ };
62
+ while (true) {
63
+ const match = re.exec(line);
64
+ if (match === null)
65
+ break;
66
+ const j = match.index;
67
+ addSpan(line.substring(i, j));
68
+ i = j + match[0].length;
69
+ if (match[1] === undefined)
70
+ continue;
71
+ for (const colorCode of match[1].split(";")) {
72
+ switch (parseInt(colorCode)) {
73
+ case 0:
74
+ // reset
75
+ this.state.bold = false;
76
+ this.state.italic = false;
77
+ this.state.underline = false;
78
+ this.state.strikethrough = false;
79
+ this.state.foregroundColor = null;
80
+ this.state.backgroundColor = null;
81
+ this.state.secret = false;
82
+ this.state.blink = false;
83
+ this.state.rapidBlink = false;
84
+ break;
85
+ case 1:
86
+ this.state.bold = true;
87
+ break;
88
+ case 3:
89
+ this.state.italic = true;
90
+ break;
91
+ case 4:
92
+ this.state.underline = true;
93
+ break;
94
+ case 5:
95
+ this.state.blink = true;
96
+ this.state.rapidBlink = false;
97
+ break;
98
+ case 6:
99
+ this.state.rapidBlink = true;
100
+ this.state.blink = false;
101
+ break;
102
+ case 8:
103
+ this.state.secret = true;
104
+ break;
105
+ case 9:
106
+ this.state.strikethrough = true;
107
+ break;
108
+ case 22:
109
+ this.state.bold = false;
110
+ break;
111
+ case 23:
112
+ this.state.italic = false;
113
+ break;
114
+ case 24:
115
+ this.state.underline = false;
116
+ break;
117
+ case 25:
118
+ this.state.blink = false;
119
+ this.state.rapidBlink = false;
120
+ break;
121
+ case 28:
122
+ this.state.secret = false;
123
+ break;
124
+ case 29:
125
+ this.state.strikethrough = false;
126
+ break;
127
+ case 30:
128
+ this.state.foregroundColor = "black";
129
+ break;
130
+ case 31:
131
+ this.state.foregroundColor = "red";
132
+ break;
133
+ case 32:
134
+ this.state.foregroundColor = "green";
135
+ break;
136
+ case 33:
137
+ this.state.foregroundColor = "yellow";
138
+ break;
139
+ case 34:
140
+ this.state.foregroundColor = "blue";
141
+ break;
142
+ case 35:
143
+ this.state.foregroundColor = "magenta";
144
+ break;
145
+ case 36:
146
+ this.state.foregroundColor = "cyan";
147
+ break;
148
+ case 37:
149
+ this.state.foregroundColor = "white";
150
+ break;
151
+ case 39:
152
+ this.state.foregroundColor = null;
153
+ break;
154
+ case 40:
155
+ this.state.backgroundColor = "black";
156
+ break;
157
+ case 41:
158
+ this.state.backgroundColor = "red";
159
+ break;
160
+ case 42:
161
+ this.state.backgroundColor = "green";
162
+ break;
163
+ case 43:
164
+ this.state.backgroundColor = "yellow";
165
+ break;
166
+ case 44:
167
+ this.state.backgroundColor = "blue";
168
+ break;
169
+ case 45:
170
+ this.state.backgroundColor = "magenta";
171
+ break;
172
+ case 46:
173
+ this.state.backgroundColor = "cyan";
174
+ break;
175
+ case 47:
176
+ this.state.backgroundColor = "white";
177
+ break;
178
+ case 49:
179
+ this.state.backgroundColor = null;
180
+ break;
181
+ }
182
+ }
183
+ }
184
+ addSpan(line.substring(i));
185
+ return lineSpan;
37
186
  }
38
-
39
- const lineSpan = document.createElement("span");
40
- lineSpan.classList.add("line");
41
- this.targetElement.appendChild(lineSpan);
42
-
43
- const addSpan = (content) => {
44
- if (content === "") return;
45
-
46
- const span = document.createElement("span");
47
- if (this.state.bold) span.classList.add("log-bold");
48
- if (this.state.italic) span.classList.add("log-italic");
49
- if (this.state.underline) span.classList.add("log-underline");
50
- if (this.state.strikethrough) span.classList.add("log-strikethrough");
51
- if (this.state.secret) span.classList.add("log-secret");
52
- if (this.state.foregroundColor !== null)
53
- span.classList.add(`log-fg-${this.state.foregroundColor}`);
54
- if (this.state.backgroundColor !== null)
55
- span.classList.add(`log-bg-${this.state.backgroundColor}`);
56
- span.appendChild(document.createTextNode(content));
57
- lineSpan.appendChild(span);
58
-
59
- if (this.state.secret) {
60
- const redacted = document.createElement("span");
61
- redacted.classList.add("log-secret-redacted");
62
- redacted.appendChild(document.createTextNode("[redacted]"));
63
- lineSpan.appendChild(redacted);
64
- }
65
- };
66
-
67
- while (true) {
68
- const match = re.exec(line);
69
- if (match === null) break;
70
-
71
- const j = match.index;
72
- addSpan(line.substring(i, j));
73
- i = j + match[0].length;
74
-
75
- if (match[1] === undefined) continue;
76
-
77
- for (const colorCode of match[1].split(";")) {
78
- switch (parseInt(colorCode)) {
79
- case 0:
80
- // reset
81
- this.state.bold = false;
82
- this.state.italic = false;
83
- this.state.underline = false;
84
- this.state.strikethrough = false;
85
- this.state.foregroundColor = null;
86
- this.state.backgroundColor = null;
87
- this.state.secret = false;
88
- break;
89
- case 1:
90
- this.state.bold = true;
91
- break;
92
- case 3:
93
- this.state.italic = true;
94
- break;
95
- case 4:
96
- this.state.underline = true;
97
- break;
98
- case 5:
99
- this.state.secret = true;
100
- break;
101
- case 6:
102
- this.state.secret = false;
103
- break;
104
- case 9:
105
- this.state.strikethrough = true;
106
- break;
107
- case 22:
108
- this.state.bold = false;
109
- break;
110
- case 23:
111
- this.state.italic = false;
112
- break;
113
- case 24:
114
- this.state.underline = false;
115
- break;
116
- case 29:
117
- this.state.strikethrough = false;
118
- break;
119
- case 30:
120
- this.state.foregroundColor = "black";
121
- break;
122
- case 31:
123
- this.state.foregroundColor = "red";
124
- break;
125
- case 32:
126
- this.state.foregroundColor = "green";
127
- break;
128
- case 33:
129
- this.state.foregroundColor = "yellow";
130
- break;
131
- case 34:
132
- this.state.foregroundColor = "blue";
133
- break;
134
- case 35:
135
- this.state.foregroundColor = "magenta";
136
- break;
137
- case 36:
138
- this.state.foregroundColor = "cyan";
139
- break;
140
- case 37:
141
- this.state.foregroundColor = "white";
142
- break;
143
- case 39:
144
- this.state.foregroundColor = null;
145
- break;
146
- case 41:
147
- this.state.backgroundColor = "red";
148
- break;
149
- case 42:
150
- this.state.backgroundColor = "green";
151
- break;
152
- case 43:
153
- this.state.backgroundColor = "yellow";
154
- break;
155
- case 44:
156
- this.state.backgroundColor = "blue";
157
- break;
158
- case 45:
159
- this.state.backgroundColor = "magenta";
160
- break;
161
- case 46:
162
- this.state.backgroundColor = "cyan";
163
- break;
164
- case 47:
165
- this.state.backgroundColor = "white";
166
- break;
167
- case 40:
168
- this.state.backgroundColor = "black";
169
- break;
170
- case 49:
171
- this.state.backgroundColor = null;
172
- break;
187
+ processLines() {
188
+ const atBottom = this.targetElement.scrollTop >
189
+ this.targetElement.scrollHeight - this.targetElement.offsetHeight - 50;
190
+ const prevCarriageReturn = this.state.carriageReturn;
191
+ const fragment = document.createDocumentFragment();
192
+ if (this.state.lines.length === 0) {
193
+ return;
194
+ }
195
+ for (const line of this.state.lines) {
196
+ // A lone \r is a pure carriage-return signal — update state but don't
197
+ // create a DOM node for it (it has no renderable content).
198
+ if (line === "\r") {
199
+ this.state.carriageReturn = true;
200
+ continue;
201
+ }
202
+ if (this.state.carriageReturn && line !== "\n") {
203
+ if (fragment.childElementCount) {
204
+ fragment.removeChild(fragment.lastChild);
205
+ }
206
+ }
207
+ const hadCarriageReturn = line.endsWith("\r");
208
+ fragment.appendChild(this.processLine(line.replace(/\r/g, "")));
209
+ this.state.carriageReturn = hadCarriageReturn;
210
+ }
211
+ if (prevCarriageReturn &&
212
+ fragment.childElementCount > 0 &&
213
+ this.targetElement.lastChild) {
214
+ this.targetElement.replaceChild(fragment, this.targetElement.lastChild);
215
+ }
216
+ else {
217
+ this.targetElement.appendChild(fragment);
218
+ }
219
+ this.state.lines = [];
220
+ // Keep scroll at bottom
221
+ if (atBottom) {
222
+ this.targetElement.scrollTop = this.targetElement.scrollHeight;
173
223
  }
174
- }
175
224
  }
176
-
177
- // Use percentage-based threshold (5% of viewport height) for better UX across screen sizes
178
- const scrollThreshold = this.targetElement.offsetHeight * 0.05;
179
- const atBottom =
180
- this.targetElement.scrollTop >
181
- this.targetElement.scrollHeight - this.targetElement.offsetHeight - scrollThreshold;
182
-
183
- addSpan(line.substring(i));
184
-
185
- // Keep scroll at bottom
186
- if (atBottom) {
187
- this.targetElement.scrollTop = this.targetElement.scrollHeight;
225
+ addLine(line) {
226
+ // Processing of lines is deferred for performance reasons
227
+ if (this.state.lines.length === 0) {
228
+ setTimeout(() => this.processLines(), 0);
229
+ }
230
+ this.state.lines.push(line);
188
231
  }
189
- }
190
232
  }
191
-
192
233
  export const coloredConsoleStyles = `
193
234
  .log {
194
235
  flex: 1;
@@ -199,11 +240,10 @@ export const coloredConsoleStyles = `
199
240
  padding: 16px;
200
241
  overflow: auto;
201
242
  line-height: 1.45;
202
- border-radius: 0;
243
+ border-radius: 3px;
203
244
  white-space: pre-wrap;
204
245
  overflow-wrap: break-word;
205
246
  color: #ddd;
206
- min-height: 0;
207
247
  }
208
248
 
209
249
  .log-bold {
@@ -221,6 +261,17 @@ export const coloredConsoleStyles = `
221
261
  .log-underline.log-strikethrough {
222
262
  text-decoration: underline line-through;
223
263
  }
264
+ .log-blink {
265
+ animation: blink 1s step-end infinite;
266
+ }
267
+ .log-rapid-blink {
268
+ animation: blink 0.4s step-end infinite;
269
+ }
270
+ @keyframes blink {
271
+ 50% {
272
+ opacity: 0;
273
+ }
274
+ }
224
275
  .log-secret {
225
276
  -webkit-user-select: none;
226
277
  -moz-user-select: none;
@@ -1,19 +1,31 @@
1
1
  export class LineBreakTransformer {
2
- constructor() {
3
- this.chunks = "";
4
- }
5
-
6
- transform(chunk, controller) {
7
- // Append new chunks to existing chunks.
8
- this.chunks += chunk;
9
- // For each line breaks in chunks, send the parsed lines out.
10
- const lines = this.chunks.split("\r\n");
11
- this.chunks = lines.pop();
12
- lines.forEach((line) => controller.enqueue(line + "\r\n"));
13
- }
14
-
15
- flush(controller) {
16
- // When the stream is closed, flush any remaining chunks out.
17
- controller.enqueue(this.chunks);
18
- }
2
+ constructor() {
3
+ this.chunks = "";
4
+ }
5
+ transform(chunk, controller) {
6
+ // Append new chunks to existing chunks.
7
+ this.chunks += chunk;
8
+ // Split on \r\n, lone \r, or lone \n — capturing the separator so we can
9
+ // distinguish a lone \r (overwrite intent) from a normal newline.
10
+ const re = /\r\n|\r|\n/g;
11
+ let lastIndex = 0;
12
+ let match;
13
+ while ((match = re.exec(this.chunks)) !== null) {
14
+ // If this is a lone \r at the very end of the buffer, leave it so it can
15
+ // be combined with a possible following \n in the next chunk.
16
+ if (match[0] === "\r" && match.index === this.chunks.length - 1) {
17
+ break;
18
+ }
19
+ const line = this.chunks.substring(lastIndex, match.index);
20
+ // Emit with \r suffix only for lone \r (overwrite), \n for everything else.
21
+ const suffix = match[0] === "\r" ? "\r" : "\n";
22
+ controller.enqueue(line + suffix);
23
+ lastIndex = re.lastIndex;
24
+ }
25
+ this.chunks = this.chunks.substring(lastIndex);
26
+ }
27
+ flush(controller) {
28
+ // When the stream is closed, flush any remaining chunks out.
29
+ controller.enqueue(this.chunks);
30
+ }
19
31
  }
@@ -0,0 +1,39 @@
1
+ // Matches lines that already carry a wall-clock or tick timestamp so we don't
2
+ // add a redundant one. Intentionally does NOT match bare log-level prefixes
3
+ // like ESPHome's [I][tag:line]: — those have no time information.
4
+ //
5
+ // Covered formats:
6
+ // (123456) FreeRTOS ms-tick e.g. "(12345) "
7
+ // [HH:MM:SS] wall-clock bracket
8
+ // [HH:MM:SS.mmm] wall-clock bracket with millis
9
+ // I (1234) tag: ESP-IDF log level + tick e.g. "I (1234) wifi: ..."
10
+ // HH:MM:SS.mmm plain wall-clock
11
+ const DEVICE_TIMESTAMP_RE = /^\s*(?:\(\d+\)\s|\[\d{2}:\d{2}:\d{2}(?:\.\d+)?\]|[DIWEACV] \(\d+\) \w|(?:\d{2}:){2}\d{2}\.\d)/;
12
+ export class TimestampTransformer {
13
+ constructor() {
14
+ this.deviceHasTimestamps = false;
15
+ }
16
+ transform(chunk, controller) {
17
+ // Pass through pure newline / empty sentinel unchanged so that
18
+ // carriage-return overwrite logic in console-color.ts still works.
19
+ if (chunk === "" || chunk === "\n" || chunk === "\r") {
20
+ controller.enqueue(chunk);
21
+ return;
22
+ }
23
+ if (!this.deviceHasTimestamps && DEVICE_TIMESTAMP_RE.test(chunk)) {
24
+ this.deviceHasTimestamps = true;
25
+ }
26
+ if (this.deviceHasTimestamps) {
27
+ controller.enqueue(chunk);
28
+ return;
29
+ }
30
+ const date = new Date();
31
+ const h = date.getHours().toString().padStart(2, "0");
32
+ const m = date.getMinutes().toString().padStart(2, "0");
33
+ const s = date.getSeconds().toString().padStart(2, "0");
34
+ controller.enqueue(`[${h}:${m}:${s}] ${chunk}`);
35
+ }
36
+ reset() {
37
+ this.deviceHasTimestamps = false;
38
+ }
39
+ }
package/package.cli.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "esp32tool",
3
- "version": "1.3.2",
3
+ "version": "1.6.5",
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.5",
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,17 +17,18 @@
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
- "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});\"",
24
- "build": "npm run prebuild && node update-sw-version.cjs && tsc --skipLibCheck && rollup -c && node -e \"const fs=require('fs'); fs.readdirSync('dist/web').filter(f=>f.endsWith('.js')).forEach(f=>fs.copyFileSync('dist/web/'+f,'js/modules/'+f)); fs.renameSync('js/modules/index.js','js/modules/esptool.js');\" && node fix-cli-imports.cjs",
23
+ "prebuild": "node -e \"const fs=require('fs'); fs.rmSync('dist',{recursive:true,force:true}); fs.rmSync('js/modules',{recursive:true,force:true}); fs.rmSync('js/util',{recursive:true,force:true}); fs.mkdirSync('js/modules',{recursive:true}); fs.mkdirSync('js/util',{recursive:true});\"",
24
+ "build": "npm run prebuild && node update-sw-version.cjs && tsc --skipLibCheck && tsc -p tsconfig.util.json && rollup -c && node -e \"const fs=require('fs'); fs.readdirSync('dist/web').filter(f=>f.endsWith('.js')).forEach(f=>fs.copyFileSync('dist/web/'+f,'js/modules/'+f)); fs.renameSync('js/modules/index.js','js/modules/esptool.js');\" && node fix-cli-imports.cjs",
25
25
  "build:binary": "node build-single-binary.cjs",
26
26
  "build:cli-electron": "node build-electron-cli.cjs",
27
27
  "format": "npm exec -- prettier --write src",
28
28
  "dev:clean": "node -e \"const fs=require('fs'); fs.rmSync('dist',{recursive:true,force:true});\"",
29
29
  "dev:tsc-once": "tsc",
30
30
  "dev:tsc": "tsc --watch",
31
+ "dev:tsc-util": "tsc -p tsconfig.util.json --watch",
31
32
  "dev:rollup": "rollup -c --watch",
32
33
  "dev:serve": "serve -p 5004",
33
34
  "develop": "npm run dev:clean && npm run dev:tsc-once && npm-run-all --parallel dev:serve dev:tsc dev:rollup",
@@ -48,28 +49,28 @@
48
49
  "@electron-forge/maker-squirrel": "^7.11.1",
49
50
  "@electron-forge/maker-zip": "^7.11.1",
50
51
  "@electron-forge/plugin-auto-unpack-natives": "^7.11.1",
51
- "@electron/fuses": "^2.0.0",
52
+ "@electron/fuses": "^2.1.1",
52
53
  "@eslint/js": "^9.39.3",
53
54
  "@rollup/plugin-json": "^6.1.0",
54
55
  "@rollup/plugin-node-resolve": "^16.0.0",
55
- "@rollup/plugin-terser": "^0.4.4",
56
+ "@rollup/plugin-terser": "^1.0.0",
56
57
  "@rollup/plugin-typescript": "^12.3.0",
57
- "@types/node": "^25.3.0",
58
+ "@types/node": "^25.5.2",
58
59
  "@types/pako": "^2.0.4",
59
60
  "@types/serialport": "^10.2.0",
60
61
  "@types/w3c-web-serial": "^1.0.7",
61
62
  "archiver": "^7.0.1",
62
- "electron": "^40.6.0",
63
+ "electron": "^41.1.0",
63
64
  "electron-squirrel-startup": "^1.0.1",
64
- "eslint": "^10.0.2",
65
+ "eslint": "^10.2.0",
65
66
  "eslint-config-prettier": "^10.1.8",
66
67
  "eslint-plugin-prettier": "^5.5.5",
67
68
  "npm-run-all": "^4.1.5",
68
69
  "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"
70
+ "rollup": "^4.60.1",
71
+ "serve": "^14.2.6",
72
+ "typescript": "^5.9.3",
73
+ "typescript-eslint": "^8.58.0"
73
74
  },
74
75
  "dependencies": {
75
76
  "pako": "^2.1.0",
@@ -83,6 +84,10 @@
83
84
  "serve": {
84
85
  "ajv": "^8.18.0"
85
86
  },
86
- "@electron/asar": "^4.0.1"
87
+ "@electron/asar": "^4.0.1",
88
+ "serialize-javascript": "^7.0.3",
89
+ "@tootallnate/once": "^3.0.1",
90
+ "http-proxy-agent": "^7.0.2",
91
+ "make-fetch-happen": "^13.0.1"
87
92
  }
88
93
  }
Binary file
Binary file