svelteesp32
Version:
Convert Svelte (or any frontend) JS application to serve it from ESP32 webserver (PsychicHttp)
621 lines (574 loc) • 16.6 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getCppCode = void 0;
const handlebars_1 = require("handlebars");
const commandLine_1 = require("./commandLine");
const cppCodeEspIdf_1 = require("./cppCodeEspIdf");
const psychicTemplate = `
//engine: PsychicHttpServer
//cmdline: {{{commandLine}}}
//You should use server.config.max_uri_handlers = {{fileCount}}; or higher value to proper handles all files
{{
//created: {{now}}
{{/if}}
//
{{
{{
{{/case}}
{{
{{/case}}
{{/switch}}
{{
{{
{{/case}}
{{
{{/case}}
{{/switch}}
//
{{
{{/if}}
//
{{
{{/each}}
//
{{
{{/each}}
//
//
{{
{{
{{
const uint8_t datagzip_{{this.dataname}}[{{this.lengthGzip}}] = { {{this.bytesGzip}} };
{{/each}}
{{/case}}
{{
{{
const uint8_t data_{{this.dataname}}[{{this.length}}] = { {{this.bytes}} };
{{/each}}
{{/case}}
{{
{{
const uint8_t datagzip_{{this.dataname}}[{{this.lengthGzip}}] = { {{this.bytesGzip}} };
{{/each}}
{{
const uint8_t data_{{this.dataname}}[{{this.length}}] = { {{this.bytes}} };
{{/each}}
{{/case}}
{{/switch}}
//
{{
{{
{{
const char * etag_{{this.dataname}} = "{{this.md5}}";
{{/each}}
{{/case}}
{{
{{/case}}
{{
{{
const char * etag_{{this.dataname}} = "{{this.md5}}";
{{/each}}
{{/case}}
{{/switch}}
//
// Http Handlers
void {{methodName}}(PsychicHttpServer * server) {
{{
//
// {{this.filename}}
{{
{{
{{
if (request->hasHeader("If-None-Match") && request->header("If-None-Match") == String(etag_{{this.dataname}})) {
PsychicResponse response304(request);
response304.setCode(304);
return response304.send();
}
{{/case}}
{{
if (request->hasHeader("If-None-Match") && request->header("If-None-Match") == String(etag_{{this.dataname}})) {
PsychicResponse response304(request);
response304.setCode(304);
return response304.send();
}
{{/case}}
{{/switch}}
PsychicResponse response(request);
response.setContentType("{{this.mime}}");
{{
{{
{{
response.addHeader("Content-Encoding", "gzip");
{{/if}}
{{/case}}
{{
{{
response.addHeader("Content-Encoding", "gzip");
{{/if}}
{{/case}}
{{/switch}}
{{
{{
{{#../cacheTime}}
response.addHeader("Cache-Control", "max-age={{value}}");
{{/../cacheTime}}
{{^../cacheTime}}
response.addHeader("Cache-Control", "no-cache");
{{/../cacheTime}}
response.addHeader("ETag", etag_{{this.dataname}});
{{/case}}
{{
{{#../cacheTime}}
response.addHeader("Cache-Control", "max-age={{value}}");
{{/../cacheTime}}
{{^../cacheTime}}
response.addHeader("Cache-Control", "no-cache");
{{/../cacheTime}}
response.addHeader("ETag", etag_{{this.dataname}});
{{/case}}
{{/switch}}
{{
{{
response.setContent(datagzip_{{this.dataname}}, {{this.lengthGzip}});
{{/case}}
{{
response.setContent(data_{{this.dataname}}, {{this.length}});
{{/case}}
{{
response.setContent(datagzip_{{this.dataname}}, {{this.lengthGzip}});
response.setContent(data_{{this.dataname}}, {{this.length}});
{{/case}}
{{/switch}}
return response.send();
});
{{/each}}
}`;
const psychic2Template = `
//engine: PsychicHttpServerV2
//cmdline: {{{commandLine}}}
{{
//created: {{now}}
{{/if}}
//
{{
{{
{{/case}}
{{
{{/case}}
{{/switch}}
{{
{{
{{/case}}
{{
{{/case}}
{{/switch}}
//
{{
{{/if}}
//
{{
{{/each}}
//
{{
{{/each}}
//
//
{{
{{
{{
const uint8_t datagzip_{{this.dataname}}[{{this.lengthGzip}}] = { {{this.bytesGzip}} };
{{/each}}
{{/case}}
{{
{{
const uint8_t data_{{this.dataname}}[{{this.length}}] = { {{this.bytes}} };
{{/each}}
{{/case}}
{{
{{
const uint8_t datagzip_{{this.dataname}}[{{this.lengthGzip}}] = { {{this.bytesGzip}} };
{{/each}}
{{
const uint8_t data_{{this.dataname}}[{{this.length}}] = { {{this.bytes}} };
{{/each}}
{{/case}}
{{/switch}}
//
{{
{{
{{
const char * etag_{{this.dataname}} = "{{this.md5}}";
{{/each}}
{{/case}}
{{
{{/case}}
{{
{{
const char * etag_{{this.dataname}} = "{{this.md5}}";
{{/each}}
{{/case}}
{{/switch}}
//
// Http Handlers
void {{methodName}}(PsychicHttpServer * server) {
{{
//
// {{this.filename}}
{{
{{
{{
if (request->hasHeader("If-None-Match") && request->header("If-None-Match") == String(etag_{{this.dataname}})) {
response->setCode(304);
return response->send();
}
{{/case}}
{{
if (request->hasHeader("If-None-Match") && request->header("If-None-Match") == String(etag_{{this.dataname}})) {
response->setCode(304);
return response->send();
}
{{/case}}
{{/switch}}
response->setContentType("{{this.mime}}");
{{
{{
{{
response->addHeader("Content-Encoding", "gzip");
{{/if}}
{{/case}}
{{
{{
response->addHeader("Content-Encoding", "gzip");
{{/if}}
{{/case}}
{{/switch}}
{{
{{
{{#../cacheTime}}
response->addHeader("Cache-Control", "max-age={{value}}");
{{/../cacheTime}}
{{^../cacheTime}}
response->addHeader("Cache-Control", "no-cache");
{{/../cacheTime}}
response->addHeader("ETag", etag_{{this.dataname}});
{{/case}}
{{
{{#../cacheTime}}
response->addHeader("Cache-Control", "max-age={{value}}");
{{/../cacheTime}}
{{^../cacheTime}}
response->addHeader("Cache-Control", "no-cache");
{{/../cacheTime}}
response->addHeader("ETag", etag_{{this.dataname}});
{{/case}}
{{/switch}}
{{
{{
response->setContent(datagzip_{{this.dataname}}, {{this.lengthGzip}});
{{/case}}
{{
response->setContent(data_{{this.dataname}}, {{this.length}});
{{/case}}
{{
response->setContent(datagzip_{{this.dataname}}, {{this.lengthGzip}});
response->setContent(data_{{this.dataname}}, {{this.length}});
{{/case}}
{{/switch}}
return response->send();
});
{{/each}}
}`;
const asyncTemplate = `
//engine: ESPAsyncWebServer
//cmdline: {{{commandLine}}}
{{
//created: {{now}}
{{/if}}
//
{{
{{
{{/case}}
{{
{{/case}}
{{/switch}}
{{
{{
{{/case}}
{{
{{/case}}
{{/switch}}
//
{{
{{/if}}
//
{{
{{/each}}
//
{{
{{/each}}
//
//
{{
{{
{{
const uint8_t datagzip_{{this.dataname}}[{{this.lengthGzip}}] PROGMEM = { {{this.bytesGzip}} };
{{/each}}
{{/case}}
{{
{{
const uint8_t data_{{this.dataname}}[{{this.length}}] PROGMEM = { {{this.bytes}} };
{{/each}}
{{/case}}
{{
{{
const uint8_t datagzip_{{this.dataname}}[{{this.lengthGzip}}] PROGMEM = { {{this.bytesGzip}} };
{{/each}}
{{
const uint8_t data_{{this.dataname}}[{{this.length}}] PROGMEM = { {{this.bytes}} };
{{/each}}
{{/case}}
{{/switch}}
//
{{
{{
{{
const char * etag_{{this.dataname}} = "{{this.md5}}";
{{/each}}
{{/case}}
{{
{{/case}}
{{
{{
const char * etag_{{this.dataname}} = "{{this.md5}}";
{{/each}}
{{/case}}
{{/switch}}
//
// Http Handlers
void {{methodName}}(AsyncWebServer * server) {
{{
//
// {{this.filename}}
ArRequestHandlerFunction func_{{this.dataname}} = [](AsyncWebServerRequest * request) {
{{
{{
if (request->hasHeader("If-None-Match") && request->getHeader("If-None-Match")->value() == String(etag_{{this.dataname}})) {
request->send(304);
return;
}
{{/case}}
{{
if (request->hasHeader("If-None-Match") && request->getHeader("If-None-Match")->value() == String(etag_{{this.dataname}})) {
request->send(304);
return;
}
{{/case}}
{{/switch}}
{{
{{
AsyncWebServerResponse *response = request->beginResponse(200, "{{this.mime}}", datagzip_{{this.dataname}}, {{this.lengthGzip}});
{{
response->addHeader("Content-Encoding", "gzip");
{{/if}}
{{/case}}
{{
AsyncWebServerResponse *response = request->beginResponse(200, "{{this.mime}}", data_{{this.dataname}}, {{this.length}});
{{/case}}
{{
AsyncWebServerResponse *response = request->beginResponse(200, "{{this.mime}}", datagzip_{{this.dataname}}, {{this.lengthGzip}});
{{
response->addHeader("Content-Encoding", "gzip");
{{/if}}
AsyncWebServerResponse *response = request->beginResponse(200, "{{this.mime}}", data_{{this.dataname}}, {{this.length}});
{{/case}}
{{/switch}}
{{
{{
{{#../cacheTime}}
response->addHeader("Cache-Control", "max-age={{value}}");
{{/../cacheTime}}
{{^../cacheTime}}
response->addHeader("Cache-Control", "no-cache");
{{/../cacheTime}}
response->addHeader("ETag", etag_{{this.dataname}});
{{/case}}
{{
{{#../cacheTime}}
response->addHeader("Cache-Control", "max-age={{value}}");
{{/../cacheTime}}
{{^../cacheTime}}
response->addHeader("Cache-Control", "no-cache");
{{/../cacheTime}}
response->addHeader("ETag", etag_{{this.dataname}});
{{/case}}
{{/switch}}
request->send(response);
};
server->on("/{{this.filename}}", HTTP_GET, func_{{this.dataname}});
{{
server->on("/", HTTP_GET, func_{{this.dataname}});
{{/if}}
{{/each}}
}`;
const getTemplate = (engine) => {
switch (engine) {
case 'psychic':
return psychicTemplate;
case 'psychic2':
return psychic2Template;
case 'espidf':
return cppCodeEspIdf_1.espidfTemplate;
default:
return asyncTemplate;
}
};
let switchValue;
const getCppCode = (sources, filesByExtension) => (0, handlebars_1.compile)(getTemplate(commandLine_1.cmdLine.engine))({
commandLine: process.argv.slice(2).join(' '),
now: `${new Date().toLocaleDateString()} ${new Date().toLocaleTimeString()}`,
fileCount: sources.length.toString(),
fileSize: sources.reduce((previous, current) => previous + current.content.length, 0).toString(),
fileGzipSize: sources.reduce((previous, current) => previous + current.contentGzip.length, 0).toString(),
sources: sources.map((s) => ({
...s,
length: s.content.length,
bytes: [...s.content].map((v) => `${v.toString(10)}`).join(','),
lengthGzip: s.contentGzip.length,
bytesGzip: [...s.contentGzip].map((v) => `${v.toString(10)}`).join(','),
isDefault: s.filename.startsWith('index.htm')
})),
filesByExtension,
etag: commandLine_1.cmdLine.etag,
gzip: commandLine_1.cmdLine.gzip,
created: commandLine_1.cmdLine.created,
version: commandLine_1.cmdLine.version,
methodName: commandLine_1.cmdLine.espmethod,
cacheTime: commandLine_1.cmdLine.cachetime ? { value: commandLine_1.cmdLine.cachetime } : undefined,
definePrefix: commandLine_1.cmdLine.define
}, {
helpers: {
ifeq: function (a, b, options) {
if (a == b)
return options.fn(this);
return options.inverse(this);
},
switch: function (value, options) {
switchValue = value;
return options.fn(this);
},
case: function (value, options) {
if (value == switchValue)
return options.fn(this);
return options.inverse(this);
}
}
})
.split('\n')
.map((line) => line.trimEnd())
.filter(Boolean)
.map((line) => (line == '//' ? '' : line))
.join('\n')
.replace(/\\n{2}/, '\n');
exports.getCppCode = getCppCode;