svelteesp32 2.0.0 → 2.1.0
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/README.md +50 -26
- package/dist/commandLine.d.ts +2 -2
- package/dist/commandLine.js +6 -4
- package/dist/cppCode.js +201 -0
- package/dist/errorMessages.js +7 -2
- package/package.json +10 -7
package/README.md
CHANGED
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
- **Smart Caching** — Built-in SHA256 ETags deliver HTTP 304 responses, slashing bandwidth on constrained devices.
|
|
26
26
|
- **CI/CD Ready** — Simple npm package that slots into any build pipeline.
|
|
27
27
|
- **Zero Runtime Overhead** — Data served directly from flash. No filesystem reads, no RAM allocation.
|
|
28
|
-
- **
|
|
28
|
+
- **4 Web Server Engines** — PsychicHttpServer V2, ESPAsyncWebServer, Arduino WebServer, and native ESP-IDF supported.
|
|
29
29
|
|
|
30
30
|
---
|
|
31
31
|
|
|
@@ -79,6 +79,8 @@ void setup() {
|
|
|
79
79
|
|
|
80
80
|
## What's New
|
|
81
81
|
|
|
82
|
+
- **v2.1.0** — New Arduino WebServer engine (`-e webserver`), dependency updates
|
|
83
|
+
- **v2.0.1** — Dependency updates (ESLint v10, eslint-plugin-unicorn 63), improved error cause chaining
|
|
82
84
|
- **v2.0.0** — **BREAKING**: PsychicHttpServer V2 is now the default `psychic` engine. The `psychic2` engine has been removed. Dry run mode, C++ identifier validation, improved MIME type warnings
|
|
83
85
|
- **v1.16.0** — Size budget constraints (`--maxsize`, `--maxgzipsize`)
|
|
84
86
|
- **v1.15.0** — `--basepath` for multiple frontends (e.g., `/admin`, `/app`)
|
|
@@ -115,6 +117,9 @@ npx svelteesp32 -e psychic -s ./dist -o ./esp32/svelteesp32.h --etag=true
|
|
|
115
117
|
# ESPAsyncWebServer (ESP32 + ESP8266)
|
|
116
118
|
npx svelteesp32 -e async -s ./dist -o ./esp32/svelteesp32.h --etag=true
|
|
117
119
|
|
|
120
|
+
# Arduino WebServer (ESP32, synchronous, no dependencies)
|
|
121
|
+
npx svelteesp32 -e webserver -s ./dist -o ./esp32/svelteesp32.h --etag=true
|
|
122
|
+
|
|
118
123
|
# Native ESP-IDF
|
|
119
124
|
npx svelteesp32 -e espidf -s ./dist -o ./esp32/svelteesp32.h --etag=true
|
|
120
125
|
```
|
|
@@ -170,6 +175,24 @@ void setup() {
|
|
|
170
175
|
}
|
|
171
176
|
```
|
|
172
177
|
|
|
178
|
+
**Arduino WebServer (built-in, no dependencies)**
|
|
179
|
+
|
|
180
|
+
```c
|
|
181
|
+
#include <WebServer.h>
|
|
182
|
+
#include "svelteesp32.h"
|
|
183
|
+
|
|
184
|
+
WebServer server(80);
|
|
185
|
+
|
|
186
|
+
void setup() {
|
|
187
|
+
initSvelteStaticFiles(&server);
|
|
188
|
+
server.begin();
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
void loop() {
|
|
192
|
+
server.handleClient();
|
|
193
|
+
}
|
|
194
|
+
```
|
|
195
|
+
|
|
173
196
|
**Native ESP-IDF**
|
|
174
197
|
|
|
175
198
|
```c
|
|
@@ -258,11 +281,12 @@ void initSvelteStaticFiles(PsychicHttpServer * server) {
|
|
|
258
281
|
|
|
259
282
|
## Supported Web Server Engines
|
|
260
283
|
|
|
261
|
-
| Engine | Flag
|
|
262
|
-
| ------------------------ |
|
|
263
|
-
| **PsychicHttpServer V2** | `-e psychic`
|
|
264
|
-
| **ESPAsyncWebServer** | `-e async`
|
|
265
|
-
| **
|
|
284
|
+
| Engine | Flag | Best For | Platform |
|
|
285
|
+
| ------------------------ | -------------- | ---------------------------- | --------------- |
|
|
286
|
+
| **PsychicHttpServer V2** | `-e psychic` | Maximum performance | ESP32 only |
|
|
287
|
+
| **ESPAsyncWebServer** | `-e async` | Cross-platform compatibility | ESP32 + ESP8266 |
|
|
288
|
+
| **Arduino WebServer** | `-e webserver` | No dependencies, simplicity | ESP32 only |
|
|
289
|
+
| **Native ESP-IDF** | `-e espidf` | Pure ESP-IDF projects | ESP32 only |
|
|
266
290
|
|
|
267
291
|
**Recommendation:** For ESP32-only projects, use PsychicHttpServer V2 (`-e psychic`) for the fastest, most stable experience.
|
|
268
292
|
|
|
@@ -287,7 +311,7 @@ Reduce bandwidth dramatically with HTTP 304 "Not Modified" responses. When a bro
|
|
|
287
311
|
- **Minimal overhead** — adds ~1-3% code size for significant bandwidth savings
|
|
288
312
|
- **Compiler mode** — use `--etag=compiler` and control via `-D SVELTEESP32_ENABLE_ETAG`
|
|
289
313
|
|
|
290
|
-
All
|
|
314
|
+
All four engines support full ETag validation.
|
|
291
315
|
|
|
292
316
|
### Browser Cache Control
|
|
293
317
|
|
|
@@ -401,25 +425,25 @@ Called for every response (200 = content served, 304 = cache hit).
|
|
|
401
425
|
|
|
402
426
|
## CLI Reference
|
|
403
427
|
|
|
404
|
-
| Option | Description
|
|
405
|
-
| ---------------- |
|
|
406
|
-
| `-s` | Source folder with compiled web files
|
|
407
|
-
| `-e` | Web server engine (psychic/async/espidf)
|
|
408
|
-
| `-o` | Output header file path
|
|
409
|
-
| `--etag` | ETag caching (true/false/compiler)
|
|
410
|
-
| `--gzip` | Gzip compression (true/false/compiler)
|
|
411
|
-
| `--exclude` | Exclude files by glob pattern
|
|
412
|
-
| `--basepath` | URL prefix for all routes
|
|
413
|
-
| `--maxsize` | Max total uncompressed size (e.g., `400k`, `1m`)
|
|
414
|
-
| `--maxgzipsize` | Max total gzip size (e.g., `150k`, `500k`)
|
|
415
|
-
| `--cachetime` | Cache-Control max-age in seconds
|
|
416
|
-
| `--version` | Version string in header
|
|
417
|
-
| `--define` | C++ define prefix
|
|
418
|
-
| `--espmethod` | Init function name
|
|
419
|
-
| `--config` | Custom RC file path
|
|
420
|
-
| `--dryrun` | Show summary without writing output
|
|
421
|
-
| `--noindexcheck` | Skip index.html validation
|
|
422
|
-
| `-h` | Show help
|
|
428
|
+
| Option | Description | Default |
|
|
429
|
+
| ---------------- | -------------------------------------------------- | ----------------------- |
|
|
430
|
+
| `-s` | Source folder with compiled web files | (required) |
|
|
431
|
+
| `-e` | Web server engine (psychic/async/espidf/webserver) | `psychic` |
|
|
432
|
+
| `-o` | Output header file path | `svelteesp32.h` |
|
|
433
|
+
| `--etag` | ETag caching (true/false/compiler) | `false` |
|
|
434
|
+
| `--gzip` | Gzip compression (true/false/compiler) | `true` |
|
|
435
|
+
| `--exclude` | Exclude files by glob pattern | System files |
|
|
436
|
+
| `--basepath` | URL prefix for all routes | (none) |
|
|
437
|
+
| `--maxsize` | Max total uncompressed size (e.g., `400k`, `1m`) | (none) |
|
|
438
|
+
| `--maxgzipsize` | Max total gzip size (e.g., `150k`, `500k`) | (none) |
|
|
439
|
+
| `--cachetime` | Cache-Control max-age in seconds | `0` |
|
|
440
|
+
| `--version` | Version string in header | (none) |
|
|
441
|
+
| `--define` | C++ define prefix | `SVELTEESP32` |
|
|
442
|
+
| `--espmethod` | Init function name | `initSvelteStaticFiles` |
|
|
443
|
+
| `--config` | Custom RC file path | `.svelteesp32rc.json` |
|
|
444
|
+
| `--dryrun` | Show summary without writing output | `false` |
|
|
445
|
+
| `--noindexcheck` | Skip index.html validation | `false` |
|
|
446
|
+
| `-h` | Show help | |
|
|
423
447
|
|
|
424
448
|
---
|
|
425
449
|
|
package/dist/commandLine.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
interface ICopyFilesArguments {
|
|
2
|
-
engine: 'psychic' | 'async' | 'espidf';
|
|
2
|
+
engine: 'psychic' | 'async' | 'espidf' | 'webserver';
|
|
3
3
|
sourcepath: string;
|
|
4
4
|
outputfile: string;
|
|
5
5
|
espmethod: string;
|
|
@@ -18,7 +18,7 @@ interface ICopyFilesArguments {
|
|
|
18
18
|
help?: boolean;
|
|
19
19
|
}
|
|
20
20
|
interface IRcFileConfig {
|
|
21
|
-
engine?: 'psychic' | 'async' | 'espidf';
|
|
21
|
+
engine?: 'psychic' | 'async' | 'espidf' | 'webserver';
|
|
22
22
|
sourcepath?: string;
|
|
23
23
|
outputfile?: string;
|
|
24
24
|
espmethod?: string;
|
package/dist/commandLine.js
CHANGED
|
@@ -24,7 +24,7 @@ Configuration:
|
|
|
24
24
|
|
|
25
25
|
Options:
|
|
26
26
|
-e, --engine <value> The engine for which the include file is created
|
|
27
|
-
(psychic|async|espidf) (default: "psychic")
|
|
27
|
+
(psychic|async|espidf|webserver) (default: "psychic")
|
|
28
28
|
-s, --sourcepath <path> Source dist folder contains compiled web files (required)
|
|
29
29
|
-o, --outputfile <path> Generated output file with path (default: "svelteesp32.h")
|
|
30
30
|
--etag <value> Use ETAG header for cache (true|false|compiler) (default: "false")
|
|
@@ -66,7 +66,7 @@ RC File:
|
|
|
66
66
|
process.exit(0);
|
|
67
67
|
}
|
|
68
68
|
function validateEngine(value) {
|
|
69
|
-
if (value === 'psychic' || value === 'async' || value === 'espidf')
|
|
69
|
+
if (value === 'psychic' || value === 'async' || value === 'espidf' || value === 'webserver')
|
|
70
70
|
return value;
|
|
71
71
|
console.error((0, errorMessages_1.getInvalidEngineError)(value));
|
|
72
72
|
process.exit(1);
|
|
@@ -151,7 +151,9 @@ function parsePackageJson(packageJsonPath) {
|
|
|
151
151
|
return JSON.parse(content);
|
|
152
152
|
}
|
|
153
153
|
catch (error) {
|
|
154
|
-
throw new Error(`Failed to parse package.json at ${packageJsonPath}: ${error.message}
|
|
154
|
+
throw new Error(`Failed to parse package.json at ${packageJsonPath}: ${error.message}`, {
|
|
155
|
+
cause: error
|
|
156
|
+
});
|
|
155
157
|
}
|
|
156
158
|
}
|
|
157
159
|
function getNpmPackageVariable(packageJson, variableName) {
|
|
@@ -242,7 +244,7 @@ function loadRcFile(rcPath) {
|
|
|
242
244
|
}
|
|
243
245
|
catch (error) {
|
|
244
246
|
if (error instanceof SyntaxError)
|
|
245
|
-
throw new Error(`Invalid JSON in RC file ${rcPath}: ${error.message}
|
|
247
|
+
throw new Error(`Invalid JSON in RC file ${rcPath}: ${error.message}`, { cause: error });
|
|
246
248
|
throw error;
|
|
247
249
|
}
|
|
248
250
|
}
|
package/dist/cppCode.js
CHANGED
|
@@ -492,6 +492,205 @@ void {{methodName}}(AsyncWebServer * server) {
|
|
|
492
492
|
});
|
|
493
493
|
{{/if}}
|
|
494
494
|
|
|
495
|
+
{{/each}}
|
|
496
|
+
}`;
|
|
497
|
+
const webserverTemplate = `
|
|
498
|
+
//engine: Arduino WebServer
|
|
499
|
+
//config: {{{config}}}
|
|
500
|
+
{{#if created }}
|
|
501
|
+
//created: {{now}}
|
|
502
|
+
{{/if}}
|
|
503
|
+
//
|
|
504
|
+
${commonHeaderSection}
|
|
505
|
+
|
|
506
|
+
//
|
|
507
|
+
#include <Arduino.h>
|
|
508
|
+
#include <WebServer.h>
|
|
509
|
+
|
|
510
|
+
//
|
|
511
|
+
${dataArraysSection(true)}
|
|
512
|
+
|
|
513
|
+
//
|
|
514
|
+
${etagArraysSection}
|
|
515
|
+
|
|
516
|
+
//
|
|
517
|
+
${manifestSection}
|
|
518
|
+
|
|
519
|
+
//
|
|
520
|
+
${hookSection}
|
|
521
|
+
|
|
522
|
+
//
|
|
523
|
+
// Chunked send helper for PROGMEM data
|
|
524
|
+
static inline void {{definePrefix}}_sendChunked(WebServer * server, const uint8_t * data, size_t len) {
|
|
525
|
+
const size_t chunkSize = 4096;
|
|
526
|
+
for (size_t offset = 0; offset < len; offset += chunkSize) {
|
|
527
|
+
size_t remaining = len - offset;
|
|
528
|
+
size_t toSend = remaining < chunkSize ? remaining : chunkSize;
|
|
529
|
+
server->sendContent_P((const char *)(data + offset), toSend);
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
//
|
|
534
|
+
// Http Handlers
|
|
535
|
+
void {{methodName}}(WebServer * server) {
|
|
536
|
+
{{#each sources}}
|
|
537
|
+
//
|
|
538
|
+
// {{this.filename}}
|
|
539
|
+
server->on("{{../basePath}}/{{this.filename}}", HTTP_GET, [server]() {
|
|
540
|
+
|
|
541
|
+
{{#switch ../etag}}
|
|
542
|
+
{{#case "true"}}
|
|
543
|
+
if (server->hasHeader("If-None-Match") && server->header("If-None-Match").equals(etag_{{this.dataname}})) {
|
|
544
|
+
server->send(304);
|
|
545
|
+
{{../definePrefix}}_onFileServed("{{../basePath}}/{{this.filename}}", 304);
|
|
546
|
+
return;
|
|
547
|
+
}
|
|
548
|
+
{{/case}}
|
|
549
|
+
{{#case "compiler"}}
|
|
550
|
+
#ifdef {{../definePrefix}}_ENABLE_ETAG
|
|
551
|
+
if (server->hasHeader("If-None-Match") && server->header("If-None-Match").equals(etag_{{this.dataname}})) {
|
|
552
|
+
server->send(304);
|
|
553
|
+
{{../definePrefix}}_onFileServed("{{../basePath}}/{{this.filename}}", 304);
|
|
554
|
+
return;
|
|
555
|
+
}
|
|
556
|
+
#endif
|
|
557
|
+
{{/case}}
|
|
558
|
+
{{/switch}}
|
|
559
|
+
|
|
560
|
+
{{#switch ../etag}}
|
|
561
|
+
{{#case "true"}}
|
|
562
|
+
{{#../cacheTime}}
|
|
563
|
+
server->sendHeader("Cache-Control", "max-age={{value}}");
|
|
564
|
+
{{/../cacheTime}}
|
|
565
|
+
{{^../cacheTime}}
|
|
566
|
+
server->sendHeader("Cache-Control", "no-cache");
|
|
567
|
+
{{/../cacheTime}}
|
|
568
|
+
server->sendHeader("ETag", etag_{{this.dataname}});
|
|
569
|
+
{{/case}}
|
|
570
|
+
{{#case "compiler"}}
|
|
571
|
+
#ifdef {{../definePrefix}}_ENABLE_ETAG
|
|
572
|
+
{{#../cacheTime}}
|
|
573
|
+
server->sendHeader("Cache-Control", "max-age={{value}}");
|
|
574
|
+
{{/../cacheTime}}
|
|
575
|
+
{{^../cacheTime}}
|
|
576
|
+
server->sendHeader("Cache-Control", "no-cache");
|
|
577
|
+
{{/../cacheTime}}
|
|
578
|
+
server->sendHeader("ETag", etag_{{this.dataname}});
|
|
579
|
+
#endif
|
|
580
|
+
{{/case}}
|
|
581
|
+
{{/switch}}
|
|
582
|
+
|
|
583
|
+
{{#switch ../gzip}}
|
|
584
|
+
{{#case "true"}}
|
|
585
|
+
{{#if this.isGzip}}
|
|
586
|
+
server->sendHeader("Content-Encoding", "gzip");
|
|
587
|
+
{{/if}}
|
|
588
|
+
server->setContentLength({{this.lengthGzip}});
|
|
589
|
+
server->send(200, "{{this.mime}}", "");
|
|
590
|
+
{{../definePrefix}}_sendChunked(server, datagzip_{{this.dataname}}, {{this.lengthGzip}});
|
|
591
|
+
{{/case}}
|
|
592
|
+
{{#case "false"}}
|
|
593
|
+
server->setContentLength({{this.length}});
|
|
594
|
+
server->send(200, "{{this.mime}}", "");
|
|
595
|
+
{{../definePrefix}}_sendChunked(server, data_{{this.dataname}}, {{this.length}});
|
|
596
|
+
{{/case}}
|
|
597
|
+
{{#case "compiler"}}
|
|
598
|
+
#ifdef {{../definePrefix}}_ENABLE_GZIP
|
|
599
|
+
{{#if this.isGzip}}
|
|
600
|
+
server->sendHeader("Content-Encoding", "gzip");
|
|
601
|
+
{{/if}}
|
|
602
|
+
server->setContentLength({{this.lengthGzip}});
|
|
603
|
+
server->send(200, "{{this.mime}}", "");
|
|
604
|
+
{{../definePrefix}}_sendChunked(server, datagzip_{{this.dataname}}, {{this.lengthGzip}});
|
|
605
|
+
#else
|
|
606
|
+
server->setContentLength({{this.length}});
|
|
607
|
+
server->send(200, "{{this.mime}}", "");
|
|
608
|
+
{{../definePrefix}}_sendChunked(server, data_{{this.dataname}}, {{this.length}});
|
|
609
|
+
#endif
|
|
610
|
+
{{/case}}
|
|
611
|
+
{{/switch}}
|
|
612
|
+
|
|
613
|
+
{{../definePrefix}}_onFileServed("{{../basePath}}/{{this.filename}}", 200);
|
|
614
|
+
});
|
|
615
|
+
{{#if this.isDefault}}
|
|
616
|
+
server->on("{{#if ../basePath}}{{../basePath}}{{else}}/{{/if}}", HTTP_GET, [server]() {
|
|
617
|
+
|
|
618
|
+
{{#switch ../etag}}
|
|
619
|
+
{{#case "true"}}
|
|
620
|
+
if (server->hasHeader("If-None-Match") && server->header("If-None-Match").equals(etag_{{this.dataname}})) {
|
|
621
|
+
server->send(304);
|
|
622
|
+
{{../definePrefix}}_onFileServed("{{#if ../basePath}}{{../basePath}}{{else}}/{{/if}}", 304);
|
|
623
|
+
return;
|
|
624
|
+
}
|
|
625
|
+
{{/case}}
|
|
626
|
+
{{#case "compiler"}}
|
|
627
|
+
#ifdef {{../definePrefix}}_ENABLE_ETAG
|
|
628
|
+
if (server->hasHeader("If-None-Match") && server->header("If-None-Match").equals(etag_{{this.dataname}})) {
|
|
629
|
+
server->send(304);
|
|
630
|
+
{{../definePrefix}}_onFileServed("{{#if ../basePath}}{{../basePath}}{{else}}/{{/if}}", 304);
|
|
631
|
+
return;
|
|
632
|
+
}
|
|
633
|
+
#endif
|
|
634
|
+
{{/case}}
|
|
635
|
+
{{/switch}}
|
|
636
|
+
|
|
637
|
+
{{#switch ../etag}}
|
|
638
|
+
{{#case "true"}}
|
|
639
|
+
{{#../cacheTime}}
|
|
640
|
+
server->sendHeader("Cache-Control", "max-age={{value}}");
|
|
641
|
+
{{/../cacheTime}}
|
|
642
|
+
{{^../cacheTime}}
|
|
643
|
+
server->sendHeader("Cache-Control", "no-cache");
|
|
644
|
+
{{/../cacheTime}}
|
|
645
|
+
server->sendHeader("ETag", etag_{{this.dataname}});
|
|
646
|
+
{{/case}}
|
|
647
|
+
{{#case "compiler"}}
|
|
648
|
+
#ifdef {{../definePrefix}}_ENABLE_ETAG
|
|
649
|
+
{{#../cacheTime}}
|
|
650
|
+
server->sendHeader("Cache-Control", "max-age={{value}}");
|
|
651
|
+
{{/../cacheTime}}
|
|
652
|
+
{{^../cacheTime}}
|
|
653
|
+
server->sendHeader("Cache-Control", "no-cache");
|
|
654
|
+
{{/../cacheTime}}
|
|
655
|
+
server->sendHeader("ETag", etag_{{this.dataname}});
|
|
656
|
+
#endif
|
|
657
|
+
{{/case}}
|
|
658
|
+
{{/switch}}
|
|
659
|
+
|
|
660
|
+
{{#switch ../gzip}}
|
|
661
|
+
{{#case "true"}}
|
|
662
|
+
{{#if this.isGzip}}
|
|
663
|
+
server->sendHeader("Content-Encoding", "gzip");
|
|
664
|
+
{{/if}}
|
|
665
|
+
server->setContentLength({{this.lengthGzip}});
|
|
666
|
+
server->send(200, "{{this.mime}}", "");
|
|
667
|
+
{{../definePrefix}}_sendChunked(server, datagzip_{{this.dataname}}, {{this.lengthGzip}});
|
|
668
|
+
{{/case}}
|
|
669
|
+
{{#case "false"}}
|
|
670
|
+
server->setContentLength({{this.length}});
|
|
671
|
+
server->send(200, "{{this.mime}}", "");
|
|
672
|
+
{{../definePrefix}}_sendChunked(server, data_{{this.dataname}}, {{this.length}});
|
|
673
|
+
{{/case}}
|
|
674
|
+
{{#case "compiler"}}
|
|
675
|
+
#ifdef {{../definePrefix}}_ENABLE_GZIP
|
|
676
|
+
{{#if this.isGzip}}
|
|
677
|
+
server->sendHeader("Content-Encoding", "gzip");
|
|
678
|
+
{{/if}}
|
|
679
|
+
server->setContentLength({{this.lengthGzip}});
|
|
680
|
+
server->send(200, "{{this.mime}}", "");
|
|
681
|
+
{{../definePrefix}}_sendChunked(server, datagzip_{{this.dataname}}, {{this.lengthGzip}});
|
|
682
|
+
#else
|
|
683
|
+
server->setContentLength({{this.length}});
|
|
684
|
+
server->send(200, "{{this.mime}}", "");
|
|
685
|
+
{{../definePrefix}}_sendChunked(server, data_{{this.dataname}}, {{this.length}});
|
|
686
|
+
#endif
|
|
687
|
+
{{/case}}
|
|
688
|
+
{{/switch}}
|
|
689
|
+
|
|
690
|
+
{{../definePrefix}}_onFileServed("{{#if ../basePath}}{{../basePath}}{{else}}/{{/if}}", 200);
|
|
691
|
+
});
|
|
692
|
+
{{/if}}
|
|
693
|
+
|
|
495
694
|
{{/each}}
|
|
496
695
|
}`;
|
|
497
696
|
const getTemplate = (engine) => {
|
|
@@ -502,6 +701,8 @@ const getTemplate = (engine) => {
|
|
|
502
701
|
return asyncTemplate;
|
|
503
702
|
case 'espidf':
|
|
504
703
|
return cppCodeEspIdf_1.espidfTemplate;
|
|
704
|
+
case 'webserver':
|
|
705
|
+
return webserverTemplate;
|
|
505
706
|
default:
|
|
506
707
|
throw new Error(`Unknown engine: ${engine}`);
|
|
507
708
|
}
|
package/dist/errorMessages.js
CHANGED
|
@@ -14,7 +14,8 @@ function getEngineName(engine) {
|
|
|
14
14
|
const names = {
|
|
15
15
|
psychic: 'PsychicHttpServer',
|
|
16
16
|
async: 'ESPAsyncWebServer',
|
|
17
|
-
espidf: 'ESP-IDF'
|
|
17
|
+
espidf: 'ESP-IDF',
|
|
18
|
+
webserver: 'Arduino WebServer'
|
|
18
19
|
};
|
|
19
20
|
return names[engine] ?? engine;
|
|
20
21
|
}
|
|
@@ -28,7 +29,10 @@ function getMissingIndexError(engine) {
|
|
|
28
29
|
3. ESPAsyncWebServer uses: server.on("/", HTTP_GET, ...)`,
|
|
29
30
|
espidf: ` 1. Add an index.html file to your source directory
|
|
30
31
|
2. The file will register both "/" and "/index.html" routes
|
|
31
|
-
3. ESP-IDF uses: httpd_register_uri_handler(server, &route_def_...)
|
|
32
|
+
3. ESP-IDF uses: httpd_register_uri_handler(server, &route_def_...)`,
|
|
33
|
+
webserver: ` 1. Add an index.html file to your source directory
|
|
34
|
+
2. The file will automatically create a "/" route handler
|
|
35
|
+
3. Arduino WebServer uses: server.on("/", HTTP_GET, handler)`
|
|
32
36
|
};
|
|
33
37
|
const hint = hints[engine] ?? hints['psychic'];
|
|
34
38
|
return ((0, consoleColor_1.redLog)('[ERROR] No index.html or index.htm found in source files') +
|
|
@@ -53,6 +57,7 @@ Valid engines are:
|
|
|
53
57
|
${(0, consoleColor_1.cyanLog)('• psychic')} - PsychicHttpServer (ESP32 only, fastest performance)
|
|
54
58
|
${(0, consoleColor_1.cyanLog)('• async')} - ESPAsyncWebServer (ESP32/ESP8266 compatible)
|
|
55
59
|
${(0, consoleColor_1.cyanLog)('• espidf')} - Native ESP-IDF web server (ESP32 only, no Arduino)
|
|
60
|
+
${(0, consoleColor_1.cyanLog)('• webserver')} - Arduino WebServer (ESP32, synchronous, built-in)
|
|
56
61
|
|
|
57
62
|
How to fix:
|
|
58
63
|
npx svelteesp32 --engine=psychic --sourcepath=./dist
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "svelteesp32",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"description": "Convert Svelte (or any frontend) JS application to serve it from ESP32 webserver (PsychicHttp)",
|
|
5
5
|
"author": "BCsabaEngine",
|
|
6
6
|
"license": "ISC",
|
|
@@ -30,6 +30,7 @@
|
|
|
30
30
|
"scripts": {
|
|
31
31
|
"dev:async": "nodemon src/index.ts -- -e async -s ./demo/svelte/dist -o ./demo/esp32/include/svelteesp32.h --etag=true --gzip=true --cachetime=86400 --version=v$npm_package_version",
|
|
32
32
|
"dev:psychic": "nodemon src/index.ts -- -e psychic -s ./demo/svelte/dist -o ./demo/esp32/include/svelteesp32.h --etag=false --gzip=false --version=v$npm_package_version",
|
|
33
|
+
"dev:webserver": "nodemon src/index.ts -- -e webserver -s ./demo/svelte/dist -o ./demo/esp32/include/svelteesp32.h --etag=true --gzip=true --cachetime=86400 --version=v$npm_package_version",
|
|
33
34
|
"test": "vitest run",
|
|
34
35
|
"test:watch": "vitest",
|
|
35
36
|
"test:coverage": "vitest run --coverage",
|
|
@@ -58,18 +59,20 @@
|
|
|
58
59
|
"espasyncwebserver"
|
|
59
60
|
],
|
|
60
61
|
"devDependencies": {
|
|
62
|
+
"@eslint/eslintrc": "^3.3.4",
|
|
63
|
+
"@eslint/js": "^10.0.1",
|
|
61
64
|
"@types/mime-types": "^3.0.1",
|
|
62
|
-
"@types/node": "^25.
|
|
65
|
+
"@types/node": "^25.3.2",
|
|
63
66
|
"@types/picomatch": "^4.0.2",
|
|
64
|
-
"@typescript-eslint/eslint-plugin": "^8.
|
|
65
|
-
"@typescript-eslint/parser": "^8.
|
|
67
|
+
"@typescript-eslint/eslint-plugin": "^8.56.1",
|
|
68
|
+
"@typescript-eslint/parser": "^8.56.1",
|
|
66
69
|
"@vitest/coverage-v8": "^4.0.18",
|
|
67
|
-
"eslint": "^
|
|
70
|
+
"eslint": "^10.0.2",
|
|
68
71
|
"eslint-config-prettier": "^10.1.8",
|
|
69
72
|
"eslint-plugin-simple-import-sort": "^12.1.1",
|
|
70
|
-
"eslint-plugin-unicorn": "^
|
|
73
|
+
"eslint-plugin-unicorn": "^63.0.0",
|
|
71
74
|
"memfs": "^4.56.10",
|
|
72
|
-
"nodemon": "^3.1.
|
|
75
|
+
"nodemon": "^3.1.14",
|
|
73
76
|
"prettier": "^3.8.1",
|
|
74
77
|
"ts-node": "^10.9.2",
|
|
75
78
|
"tsx": "^4.21.0",
|