svelteesp32 3.0.2 → 3.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 +38 -37
- package/dist/commandLine.js +9 -9
- package/dist/cppCode.d.ts +49 -0
- package/dist/cppCode.js +107 -985
- package/dist/cppCodeAsync.d.ts +2 -0
- package/dist/cppCodeAsync.js +101 -0
- package/dist/cppCodeEspIdf.d.ts +2 -1
- package/dist/cppCodeEspIdf.js +172 -266
- package/dist/cppCodePsychic.d.ts +2 -0
- package/dist/cppCodePsychic.js +105 -0
- package/dist/cppCodeWebserver.d.ts +2 -0
- package/dist/cppCodeWebserver.js +118 -0
- package/dist/index.js +2 -0
- package/package.json +7 -7
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.genPsychicCpp = void 0;
|
|
4
|
+
const cppCode_1 = require("./cppCode");
|
|
5
|
+
const genPsychicHandlerBody = (d, source, path) => {
|
|
6
|
+
const lines = [];
|
|
7
|
+
const etagCheck = (0, cppCode_1.sw)(d.etag, {
|
|
8
|
+
always: [
|
|
9
|
+
` if (request->hasHeader("If-None-Match") && request->header("If-None-Match").equals(etag_${source.dataname})) {`,
|
|
10
|
+
` response->setCode(304);`,
|
|
11
|
+
` ${d.definePrefix}_onFileServed("${path}", 304);`,
|
|
12
|
+
` return response->send();`,
|
|
13
|
+
` }`
|
|
14
|
+
].join('\n'),
|
|
15
|
+
compiler: [
|
|
16
|
+
` #ifdef ${d.definePrefix}_ENABLE_ETAG`,
|
|
17
|
+
` if (request->hasHeader("If-None-Match") && request->header("If-None-Match").equals(etag_${source.dataname})) {`,
|
|
18
|
+
` response->setCode(304);`,
|
|
19
|
+
` ${d.definePrefix}_onFileServed("${path}", 304);`,
|
|
20
|
+
` return response->send();`,
|
|
21
|
+
` }`,
|
|
22
|
+
` #endif`
|
|
23
|
+
].join('\n')
|
|
24
|
+
});
|
|
25
|
+
if (etagCheck)
|
|
26
|
+
lines.push(etagCheck);
|
|
27
|
+
lines.push(` response->setContentType("${source.mime}");`);
|
|
28
|
+
const gzipEncoding = (0, cppCode_1.sw)(d.gzip, {
|
|
29
|
+
always: source.isGzip ? ` response->addHeader("Content-Encoding", "gzip");` : '',
|
|
30
|
+
compiler: source.isGzip
|
|
31
|
+
? [
|
|
32
|
+
` #ifdef ${d.definePrefix}_ENABLE_GZIP`,
|
|
33
|
+
` response->addHeader("Content-Encoding", "gzip");`,
|
|
34
|
+
` #endif`
|
|
35
|
+
].join('\n')
|
|
36
|
+
: ''
|
|
37
|
+
});
|
|
38
|
+
if (gzipEncoding)
|
|
39
|
+
lines.push(gzipEncoding);
|
|
40
|
+
const cacheHeaders = (0, cppCode_1.sw)(d.etag, {
|
|
41
|
+
always: [
|
|
42
|
+
` response->addHeader("Cache-Control", "${(0, cppCode_1.cacheCtrl)(source)}");`,
|
|
43
|
+
` response->addHeader("ETag", etag_${source.dataname});`
|
|
44
|
+
].join('\n'),
|
|
45
|
+
compiler: [
|
|
46
|
+
` #ifdef ${d.definePrefix}_ENABLE_ETAG`,
|
|
47
|
+
` response->addHeader("Cache-Control", "${(0, cppCode_1.cacheCtrl)(source)}");`,
|
|
48
|
+
` response->addHeader("ETag", etag_${source.dataname});`,
|
|
49
|
+
` #endif`
|
|
50
|
+
].join('\n')
|
|
51
|
+
});
|
|
52
|
+
if (cacheHeaders)
|
|
53
|
+
lines.push(cacheHeaders);
|
|
54
|
+
lines.push((0, cppCode_1.sw)(d.gzip, {
|
|
55
|
+
always: ` response->setContent(datagzip_${source.dataname}, ${source.lengthGzip});`,
|
|
56
|
+
never: ` response->setContent(data_${source.dataname}, ${source.length});`,
|
|
57
|
+
compiler: [
|
|
58
|
+
` #ifdef ${d.definePrefix}_ENABLE_GZIP`,
|
|
59
|
+
` response->setContent(datagzip_${source.dataname}, ${source.lengthGzip});`,
|
|
60
|
+
` #else`,
|
|
61
|
+
` response->setContent(data_${source.dataname}, ${source.length});`,
|
|
62
|
+
` #endif`
|
|
63
|
+
].join('\n')
|
|
64
|
+
}), ` ${d.definePrefix}_onFileServed("${path}", 200);`, ` return response->send();`);
|
|
65
|
+
return lines.join('\n');
|
|
66
|
+
};
|
|
67
|
+
const genPsychicCpp = (d) => {
|
|
68
|
+
const lines = [
|
|
69
|
+
`//engine: PsychicHttpServer`,
|
|
70
|
+
`//config: ${d.config}`,
|
|
71
|
+
...(d.created ? [`//created: ${d.now}`] : []),
|
|
72
|
+
'//',
|
|
73
|
+
(0, cppCode_1.genCommonHeader)(d),
|
|
74
|
+
'//',
|
|
75
|
+
'#include <Arduino.h>',
|
|
76
|
+
'#include <PsychicHttp.h>',
|
|
77
|
+
'#include <PsychicHttpsServer.h>',
|
|
78
|
+
'//',
|
|
79
|
+
(0, cppCode_1.genDataArrays)(d, false),
|
|
80
|
+
'//',
|
|
81
|
+
(0, cppCode_1.genEtagArrays)(d),
|
|
82
|
+
'//',
|
|
83
|
+
(0, cppCode_1.genManifest)(d),
|
|
84
|
+
'//',
|
|
85
|
+
(0, cppCode_1.genHook)(d),
|
|
86
|
+
'//',
|
|
87
|
+
'// Http Handlers',
|
|
88
|
+
`void ${d.methodName}(PsychicHttpServer * server) {`
|
|
89
|
+
];
|
|
90
|
+
for (const source of d.sources) {
|
|
91
|
+
const path = `${d.basePath}/${source.filename}`;
|
|
92
|
+
const serverPrefix = source.isDefault && !d.basePath ? 'server->defaultEndpoint = ' : '';
|
|
93
|
+
lines.push('//', `// ${source.filename}`, ` ${serverPrefix}server->on("${path}", HTTP_GET, [](PsychicRequest * request, PsychicResponse * response) {`, genPsychicHandlerBody(d, source, path), ` });`);
|
|
94
|
+
if (source.isDefault && d.basePath)
|
|
95
|
+
lines.push('//', `// ${source.filename} (base path route)`, ` server->on("${d.basePath}", HTTP_GET, [](PsychicRequest * request, PsychicResponse * response) {`, genPsychicHandlerBody(d, source, d.basePath), ` });`);
|
|
96
|
+
}
|
|
97
|
+
if (d.spa && d.spaSource && d.basePath) {
|
|
98
|
+
const source = d.spaSource;
|
|
99
|
+
const path = `${d.basePath}/${source.filename}`;
|
|
100
|
+
lines.push('//', `// SPA catch-all: unmatched routes serve ${source.filename}`, ` server->on("${d.basePath}/*", HTTP_GET, [](PsychicRequest * request, PsychicResponse * response) {`, genPsychicHandlerBody(d, source, path), ` });`);
|
|
101
|
+
}
|
|
102
|
+
lines.push('}');
|
|
103
|
+
return lines.join('\n');
|
|
104
|
+
};
|
|
105
|
+
exports.genPsychicCpp = genPsychicCpp;
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.genWebserverCpp = void 0;
|
|
4
|
+
const cppCode_1 = require("./cppCode");
|
|
5
|
+
const genWebserverHandlerBody = (d, source, path) => {
|
|
6
|
+
const lines = [];
|
|
7
|
+
const etagCheck = (0, cppCode_1.sw)(d.etag, {
|
|
8
|
+
always: [
|
|
9
|
+
` if (server->hasHeader("If-None-Match") && server->header("If-None-Match").equals(etag_${source.dataname})) {`,
|
|
10
|
+
` server->send(304);`,
|
|
11
|
+
` ${d.definePrefix}_onFileServed("${path}", 304);`,
|
|
12
|
+
` return;`,
|
|
13
|
+
` }`
|
|
14
|
+
].join('\n'),
|
|
15
|
+
compiler: [
|
|
16
|
+
` #ifdef ${d.definePrefix}_ENABLE_ETAG`,
|
|
17
|
+
` if (server->hasHeader("If-None-Match") && server->header("If-None-Match").equals(etag_${source.dataname})) {`,
|
|
18
|
+
` server->send(304);`,
|
|
19
|
+
` ${d.definePrefix}_onFileServed("${path}", 304);`,
|
|
20
|
+
` return;`,
|
|
21
|
+
` }`,
|
|
22
|
+
` #endif`
|
|
23
|
+
].join('\n')
|
|
24
|
+
});
|
|
25
|
+
if (etagCheck)
|
|
26
|
+
lines.push(etagCheck);
|
|
27
|
+
const cacheHeaders = (0, cppCode_1.sw)(d.etag, {
|
|
28
|
+
always: [
|
|
29
|
+
` server->sendHeader("Cache-Control", "${(0, cppCode_1.cacheCtrl)(source)}");`,
|
|
30
|
+
` server->sendHeader("ETag", etag_${source.dataname});`
|
|
31
|
+
].join('\n'),
|
|
32
|
+
compiler: [
|
|
33
|
+
` #ifdef ${d.definePrefix}_ENABLE_ETAG`,
|
|
34
|
+
` server->sendHeader("Cache-Control", "${(0, cppCode_1.cacheCtrl)(source)}");`,
|
|
35
|
+
` server->sendHeader("ETag", etag_${source.dataname});`,
|
|
36
|
+
` #endif`
|
|
37
|
+
].join('\n')
|
|
38
|
+
});
|
|
39
|
+
if (cacheHeaders)
|
|
40
|
+
lines.push(cacheHeaders);
|
|
41
|
+
lines.push((0, cppCode_1.sw)(d.gzip, {
|
|
42
|
+
always: [
|
|
43
|
+
...(source.isGzip ? [` server->sendHeader("Content-Encoding", "gzip");`] : []),
|
|
44
|
+
` server->setContentLength(${source.lengthGzip});`,
|
|
45
|
+
` server->send(200, "${source.mime}", "");`,
|
|
46
|
+
` ${d.definePrefix}_sendChunked(server, datagzip_${source.dataname}, ${source.lengthGzip});`
|
|
47
|
+
].join('\n'),
|
|
48
|
+
never: [
|
|
49
|
+
` server->setContentLength(${source.length});`,
|
|
50
|
+
` server->send(200, "${source.mime}", "");`,
|
|
51
|
+
` ${d.definePrefix}_sendChunked(server, data_${source.dataname}, ${source.length});`
|
|
52
|
+
].join('\n'),
|
|
53
|
+
compiler: [
|
|
54
|
+
` #ifdef ${d.definePrefix}_ENABLE_GZIP`,
|
|
55
|
+
...(source.isGzip ? [` server->sendHeader("Content-Encoding", "gzip");`] : []),
|
|
56
|
+
` server->setContentLength(${source.lengthGzip});`,
|
|
57
|
+
` server->send(200, "${source.mime}", "");`,
|
|
58
|
+
` ${d.definePrefix}_sendChunked(server, datagzip_${source.dataname}, ${source.lengthGzip});`,
|
|
59
|
+
` #else`,
|
|
60
|
+
` server->setContentLength(${source.length});`,
|
|
61
|
+
` server->send(200, "${source.mime}", "");`,
|
|
62
|
+
` ${d.definePrefix}_sendChunked(server, data_${source.dataname}, ${source.length});`,
|
|
63
|
+
` #endif`
|
|
64
|
+
].join('\n')
|
|
65
|
+
}), ` ${d.definePrefix}_onFileServed("${path}", 200);`);
|
|
66
|
+
return lines.join('\n');
|
|
67
|
+
};
|
|
68
|
+
const genWebserverCpp = (d) => {
|
|
69
|
+
const lines = [
|
|
70
|
+
`//engine: Arduino WebServer`,
|
|
71
|
+
`//config: ${d.config}`,
|
|
72
|
+
...(d.created ? [`//created: ${d.now}`] : []),
|
|
73
|
+
'//',
|
|
74
|
+
(0, cppCode_1.genCommonHeader)(d),
|
|
75
|
+
'//',
|
|
76
|
+
'#include <Arduino.h>',
|
|
77
|
+
'#include <WebServer.h>',
|
|
78
|
+
'//',
|
|
79
|
+
(0, cppCode_1.genDataArrays)(d, true),
|
|
80
|
+
'//',
|
|
81
|
+
(0, cppCode_1.genEtagArrays)(d),
|
|
82
|
+
'//',
|
|
83
|
+
(0, cppCode_1.genManifest)(d),
|
|
84
|
+
'//',
|
|
85
|
+
(0, cppCode_1.genHook)(d),
|
|
86
|
+
'//',
|
|
87
|
+
`// Chunked send helper for PROGMEM data`,
|
|
88
|
+
`static inline void ${d.definePrefix}_sendChunked(WebServer * server, const uint8_t * data, size_t len) {`,
|
|
89
|
+
` const size_t chunkSize = 4096;`,
|
|
90
|
+
` for (size_t offset = 0; offset < len; offset += chunkSize) {`,
|
|
91
|
+
` size_t remaining = len - offset;`,
|
|
92
|
+
` size_t toSend = remaining < chunkSize ? remaining : chunkSize;`,
|
|
93
|
+
` server->sendContent_P((const char *)(data + offset), toSend);`,
|
|
94
|
+
` }`,
|
|
95
|
+
`}`,
|
|
96
|
+
'//',
|
|
97
|
+
'// Http Handlers',
|
|
98
|
+
`void ${d.methodName}(WebServer * server) {`
|
|
99
|
+
];
|
|
100
|
+
for (const source of d.sources) {
|
|
101
|
+
const path = `${d.basePath}/${source.filename}`;
|
|
102
|
+
const defaultPath = d.basePath || '/';
|
|
103
|
+
lines.push('//', `// ${source.filename}`, ` server->on("${path}", HTTP_GET, [server]() {`, genWebserverHandlerBody(d, source, path), ` });`);
|
|
104
|
+
if (source.isDefault)
|
|
105
|
+
lines.push(` server->on("${defaultPath}", HTTP_GET, [server]() {`, genWebserverHandlerBody(d, source, defaultPath), ` });`);
|
|
106
|
+
}
|
|
107
|
+
if (d.spa && d.spaSource) {
|
|
108
|
+
const source = d.spaSource;
|
|
109
|
+
const path = `${d.basePath}/${source.filename}`;
|
|
110
|
+
lines.push('//', `// SPA catch-all: unmatched routes serve ${source.filename}`, ` server->onNotFound([server]() {`, ` if (server->method() != HTTP_GET) { server->send(404, "text/plain", "Not found"); return; }`);
|
|
111
|
+
if (d.basePath)
|
|
112
|
+
lines.push(` if (!server->uri().startsWith("${d.basePath}/") && server->uri() != "${d.basePath}") { server->send(404, "text/plain", "Not found"); return; }`);
|
|
113
|
+
lines.push(genWebserverHandlerBody(d, source, path), ` });`);
|
|
114
|
+
}
|
|
115
|
+
lines.push('}');
|
|
116
|
+
return lines.join('\n');
|
|
117
|
+
};
|
|
118
|
+
exports.genWebserverCpp = genWebserverCpp;
|
package/dist/index.js
CHANGED
|
@@ -40,3 +40,5 @@ Object.defineProperty(exports, "formatSize", { enumerable: true, get: function (
|
|
|
40
40
|
Object.defineProperty(exports, "formatSizePrecise", { enumerable: true, get: function () { return pipeline_2.formatSizePrecise; } });
|
|
41
41
|
Object.defineProperty(exports, "shouldUseGzip", { enumerable: true, get: function () { return pipeline_2.shouldUseGzip; } });
|
|
42
42
|
Object.defineProperty(exports, "updateExtensionGroup", { enumerable: true, get: function () { return pipeline_2.updateExtensionGroup; } });
|
|
43
|
+
if (require.main === module)
|
|
44
|
+
main();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "svelteesp32",
|
|
3
|
-
"version": "3.0
|
|
3
|
+
"version": "3.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",
|
|
@@ -72,11 +72,11 @@
|
|
|
72
72
|
"devDependencies": {
|
|
73
73
|
"@eslint/js": "^10.0.1",
|
|
74
74
|
"@types/mime-types": "^3.0.1",
|
|
75
|
-
"@types/node": "^25.6.
|
|
75
|
+
"@types/node": "^25.6.2",
|
|
76
76
|
"@types/picomatch": "^4.0.3",
|
|
77
|
-
"@typescript-eslint/eslint-plugin": "^8.59.
|
|
78
|
-
"@typescript-eslint/parser": "^8.59.
|
|
79
|
-
"@vitest/coverage-v8": "^4.1.
|
|
77
|
+
"@typescript-eslint/eslint-plugin": "^8.59.3",
|
|
78
|
+
"@typescript-eslint/parser": "^8.59.3",
|
|
79
|
+
"@vitest/coverage-v8": "^4.1.6",
|
|
80
80
|
"eslint": "^10.3.0",
|
|
81
81
|
"eslint-config-prettier": "^10.1.8",
|
|
82
82
|
"eslint-plugin-simple-import-sort": "^13.0.0",
|
|
@@ -85,9 +85,10 @@
|
|
|
85
85
|
"memfs": "^4.57.2",
|
|
86
86
|
"nodemon": "^3.1.14",
|
|
87
87
|
"prettier": "^3.8.3",
|
|
88
|
+
"ts-node": "^10.9.2",
|
|
88
89
|
"tsx": "^4.21.0",
|
|
89
90
|
"typescript": "^6.0.3",
|
|
90
|
-
"vitest": "^4.1.
|
|
91
|
+
"vitest": "^4.1.6"
|
|
91
92
|
},
|
|
92
93
|
"peerDependencies": {
|
|
93
94
|
"vite": ">=5"
|
|
@@ -98,7 +99,6 @@
|
|
|
98
99
|
}
|
|
99
100
|
},
|
|
100
101
|
"dependencies": {
|
|
101
|
-
"handlebars": "^4.7.9",
|
|
102
102
|
"mime-types": "^3.0.2",
|
|
103
103
|
"picomatch": "^4.0.4",
|
|
104
104
|
"tinyglobby": "^0.2.16"
|