svelteesp32 2.0.1 → 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 +49 -26
- package/dist/commandLine.d.ts +2 -2
- package/dist/commandLine.js +2 -2
- package/dist/cppCode.js +201 -0
- package/dist/errorMessages.js +7 -2
- package/package.json +9 -8
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,7 @@ void setup() {
|
|
|
79
79
|
|
|
80
80
|
## What's New
|
|
81
81
|
|
|
82
|
+
- **v2.1.0** — New Arduino WebServer engine (`-e webserver`), dependency updates
|
|
82
83
|
- **v2.0.1** — Dependency updates (ESLint v10, eslint-plugin-unicorn 63), improved error cause chaining
|
|
83
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
|
|
84
85
|
- **v1.16.0** — Size budget constraints (`--maxsize`, `--maxgzipsize`)
|
|
@@ -116,6 +117,9 @@ npx svelteesp32 -e psychic -s ./dist -o ./esp32/svelteesp32.h --etag=true
|
|
|
116
117
|
# ESPAsyncWebServer (ESP32 + ESP8266)
|
|
117
118
|
npx svelteesp32 -e async -s ./dist -o ./esp32/svelteesp32.h --etag=true
|
|
118
119
|
|
|
120
|
+
# Arduino WebServer (ESP32, synchronous, no dependencies)
|
|
121
|
+
npx svelteesp32 -e webserver -s ./dist -o ./esp32/svelteesp32.h --etag=true
|
|
122
|
+
|
|
119
123
|
# Native ESP-IDF
|
|
120
124
|
npx svelteesp32 -e espidf -s ./dist -o ./esp32/svelteesp32.h --etag=true
|
|
121
125
|
```
|
|
@@ -171,6 +175,24 @@ void setup() {
|
|
|
171
175
|
}
|
|
172
176
|
```
|
|
173
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
|
+
|
|
174
196
|
**Native ESP-IDF**
|
|
175
197
|
|
|
176
198
|
```c
|
|
@@ -259,11 +281,12 @@ void initSvelteStaticFiles(PsychicHttpServer * server) {
|
|
|
259
281
|
|
|
260
282
|
## Supported Web Server Engines
|
|
261
283
|
|
|
262
|
-
| Engine | Flag
|
|
263
|
-
| ------------------------ |
|
|
264
|
-
| **PsychicHttpServer V2** | `-e psychic`
|
|
265
|
-
| **ESPAsyncWebServer** | `-e async`
|
|
266
|
-
| **
|
|
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 |
|
|
267
290
|
|
|
268
291
|
**Recommendation:** For ESP32-only projects, use PsychicHttpServer V2 (`-e psychic`) for the fastest, most stable experience.
|
|
269
292
|
|
|
@@ -288,7 +311,7 @@ Reduce bandwidth dramatically with HTTP 304 "Not Modified" responses. When a bro
|
|
|
288
311
|
- **Minimal overhead** — adds ~1-3% code size for significant bandwidth savings
|
|
289
312
|
- **Compiler mode** — use `--etag=compiler` and control via `-D SVELTEESP32_ENABLE_ETAG`
|
|
290
313
|
|
|
291
|
-
All
|
|
314
|
+
All four engines support full ETag validation.
|
|
292
315
|
|
|
293
316
|
### Browser Cache Control
|
|
294
317
|
|
|
@@ -402,25 +425,25 @@ Called for every response (200 = content served, 304 = cache hit).
|
|
|
402
425
|
|
|
403
426
|
## CLI Reference
|
|
404
427
|
|
|
405
|
-
| Option | Description
|
|
406
|
-
| ---------------- |
|
|
407
|
-
| `-s` | Source folder with compiled web files
|
|
408
|
-
| `-e` | Web server engine (psychic/async/espidf)
|
|
409
|
-
| `-o` | Output header file path
|
|
410
|
-
| `--etag` | ETag caching (true/false/compiler)
|
|
411
|
-
| `--gzip` | Gzip compression (true/false/compiler)
|
|
412
|
-
| `--exclude` | Exclude files by glob pattern
|
|
413
|
-
| `--basepath` | URL prefix for all routes
|
|
414
|
-
| `--maxsize` | Max total uncompressed size (e.g., `400k`, `1m`)
|
|
415
|
-
| `--maxgzipsize` | Max total gzip size (e.g., `150k`, `500k`)
|
|
416
|
-
| `--cachetime` | Cache-Control max-age in seconds
|
|
417
|
-
| `--version` | Version string in header
|
|
418
|
-
| `--define` | C++ define prefix
|
|
419
|
-
| `--espmethod` | Init function name
|
|
420
|
-
| `--config` | Custom RC file path
|
|
421
|
-
| `--dryrun` | Show summary without writing output
|
|
422
|
-
| `--noindexcheck` | Skip index.html validation
|
|
423
|
-
| `-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 | |
|
|
424
447
|
|
|
425
448
|
---
|
|
426
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);
|
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.0
|
|
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,20 +59,20 @@
|
|
|
58
59
|
"espasyncwebserver"
|
|
59
60
|
],
|
|
60
61
|
"devDependencies": {
|
|
61
|
-
"@eslint/eslintrc": "^3.3.
|
|
62
|
-
"@eslint/js": "^10.0.
|
|
62
|
+
"@eslint/eslintrc": "^3.3.4",
|
|
63
|
+
"@eslint/js": "^10.0.1",
|
|
63
64
|
"@types/mime-types": "^3.0.1",
|
|
64
|
-
"@types/node": "^25.3.
|
|
65
|
+
"@types/node": "^25.3.2",
|
|
65
66
|
"@types/picomatch": "^4.0.2",
|
|
66
|
-
"@typescript-eslint/eslint-plugin": "^8.56.
|
|
67
|
-
"@typescript-eslint/parser": "^8.56.
|
|
67
|
+
"@typescript-eslint/eslint-plugin": "^8.56.1",
|
|
68
|
+
"@typescript-eslint/parser": "^8.56.1",
|
|
68
69
|
"@vitest/coverage-v8": "^4.0.18",
|
|
69
|
-
"eslint": "^10.0.
|
|
70
|
+
"eslint": "^10.0.2",
|
|
70
71
|
"eslint-config-prettier": "^10.1.8",
|
|
71
72
|
"eslint-plugin-simple-import-sort": "^12.1.1",
|
|
72
73
|
"eslint-plugin-unicorn": "^63.0.0",
|
|
73
74
|
"memfs": "^4.56.10",
|
|
74
|
-
"nodemon": "^3.1.
|
|
75
|
+
"nodemon": "^3.1.14",
|
|
75
76
|
"prettier": "^3.8.1",
|
|
76
77
|
"ts-node": "^10.9.2",
|
|
77
78
|
"tsx": "^4.21.0",
|