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.
@@ -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,2 @@
1
+ import type { TemplateData } from './cppCode';
2
+ export declare const genWebserverCpp: (d: TemplateData) => string;
@@ -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.2",
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.0",
75
+ "@types/node": "^25.6.2",
76
76
  "@types/picomatch": "^4.0.3",
77
- "@typescript-eslint/eslint-plugin": "^8.59.2",
78
- "@typescript-eslint/parser": "^8.59.2",
79
- "@vitest/coverage-v8": "^4.1.5",
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.5"
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"