svelteesp32 1.16.0 → 2.0.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 +51 -44
- package/dist/commandLine.d.ts +10 -6
- package/dist/commandLine.js +121 -149
- package/dist/cppCode.js +19 -214
- package/dist/cppCodeEspIdf.d.ts +1 -1
- package/dist/cppCodeEspIdf.js +10 -8
- package/dist/errorMessages.d.ts +1 -1
- package/dist/errorMessages.js +3 -12
- package/dist/file.d.ts +5 -1
- package/dist/file.js +9 -6
- package/dist/index.d.ts +5 -3
- package/dist/index.js +71 -53
- package/package.json +2 -4
package/dist/cppCode.js
CHANGED
|
@@ -120,212 +120,6 @@ extern "C" void __attribute__((weak)) {{definePrefix}}_onFileServed(const char*
|
|
|
120
120
|
const psychicTemplate = `
|
|
121
121
|
//engine: PsychicHttpServer
|
|
122
122
|
//config: {{{config}}}
|
|
123
|
-
//You should use server.config.max_uri_handlers = {{fileCount}}; or higher value to proper handles all files
|
|
124
|
-
{{#if created }}
|
|
125
|
-
//created: {{now}}
|
|
126
|
-
{{/if}}
|
|
127
|
-
//
|
|
128
|
-
${commonHeaderSection}
|
|
129
|
-
|
|
130
|
-
//
|
|
131
|
-
#include <Arduino.h>
|
|
132
|
-
#include <PsychicHttp.h>
|
|
133
|
-
#include <PsychicHttpsServer.h>
|
|
134
|
-
|
|
135
|
-
//
|
|
136
|
-
${dataArraysSection(false)}
|
|
137
|
-
|
|
138
|
-
//
|
|
139
|
-
${etagArraysSection}
|
|
140
|
-
|
|
141
|
-
//
|
|
142
|
-
${manifestSection}
|
|
143
|
-
|
|
144
|
-
//
|
|
145
|
-
${hookSection}
|
|
146
|
-
|
|
147
|
-
//
|
|
148
|
-
// Http Handlers
|
|
149
|
-
void {{methodName}}(PsychicHttpServer * server) {
|
|
150
|
-
{{#each sources}}
|
|
151
|
-
//
|
|
152
|
-
// {{this.filename}}
|
|
153
|
-
{{#if this.isDefault}}{{#unless ../basePath}}server->defaultEndpoint = {{/unless}}{{/if}}server->on("{{../basePath}}/{{this.filename}}", HTTP_GET, [](PsychicRequest * request) {
|
|
154
|
-
|
|
155
|
-
{{#switch ../etag}}
|
|
156
|
-
{{#case "true"}}
|
|
157
|
-
if (request->hasHeader("If-None-Match") && request->header("If-None-Match").equals(etag_{{this.dataname}})) {
|
|
158
|
-
PsychicResponse response304(request);
|
|
159
|
-
response304.setCode(304);
|
|
160
|
-
{{../definePrefix}}_onFileServed("{{../basePath}}/{{this.filename}}", 304);
|
|
161
|
-
return response304.send();
|
|
162
|
-
}
|
|
163
|
-
{{/case}}
|
|
164
|
-
{{#case "compiler"}}
|
|
165
|
-
#ifdef {{../definePrefix}}_ENABLE_ETAG
|
|
166
|
-
if (request->hasHeader("If-None-Match") && request->header("If-None-Match").equals(etag_{{this.dataname}})) {
|
|
167
|
-
PsychicResponse response304(request);
|
|
168
|
-
response304.setCode(304);
|
|
169
|
-
{{../definePrefix}}_onFileServed("{{../basePath}}/{{this.filename}}", 304);
|
|
170
|
-
return response304.send();
|
|
171
|
-
}
|
|
172
|
-
#endif
|
|
173
|
-
{{/case}}
|
|
174
|
-
{{/switch}}
|
|
175
|
-
|
|
176
|
-
PsychicResponse response(request);
|
|
177
|
-
response.setContentType("{{this.mime}}");
|
|
178
|
-
|
|
179
|
-
{{#switch ../gzip}}
|
|
180
|
-
{{#case "true"}}
|
|
181
|
-
{{#if this.isGzip}}
|
|
182
|
-
response.addHeader("Content-Encoding", "gzip");
|
|
183
|
-
{{/if}}
|
|
184
|
-
{{/case}}
|
|
185
|
-
{{#case "compiler"}}
|
|
186
|
-
{{#if this.isGzip}}
|
|
187
|
-
#ifdef {{../definePrefix}}_ENABLE_GZIP
|
|
188
|
-
response.addHeader("Content-Encoding", "gzip");
|
|
189
|
-
#endif
|
|
190
|
-
{{/if}}
|
|
191
|
-
{{/case}}
|
|
192
|
-
{{/switch}}
|
|
193
|
-
|
|
194
|
-
{{#switch ../etag}}
|
|
195
|
-
{{#case "true"}}
|
|
196
|
-
{{#../cacheTime}}
|
|
197
|
-
response.addHeader("Cache-Control", "max-age={{value}}");
|
|
198
|
-
{{/../cacheTime}}
|
|
199
|
-
{{^../cacheTime}}
|
|
200
|
-
response.addHeader("Cache-Control", "no-cache");
|
|
201
|
-
{{/../cacheTime}}
|
|
202
|
-
response.addHeader("ETag", etag_{{this.dataname}});
|
|
203
|
-
{{/case}}
|
|
204
|
-
{{#case "compiler"}}
|
|
205
|
-
#ifdef {{../definePrefix}}_ENABLE_ETAG
|
|
206
|
-
{{#../cacheTime}}
|
|
207
|
-
response.addHeader("Cache-Control", "max-age={{value}}");
|
|
208
|
-
{{/../cacheTime}}
|
|
209
|
-
{{^../cacheTime}}
|
|
210
|
-
response.addHeader("Cache-Control", "no-cache");
|
|
211
|
-
{{/../cacheTime}}
|
|
212
|
-
response.addHeader("ETag", etag_{{this.dataname}});
|
|
213
|
-
#endif
|
|
214
|
-
{{/case}}
|
|
215
|
-
{{/switch}}
|
|
216
|
-
|
|
217
|
-
{{#switch ../gzip}}
|
|
218
|
-
{{#case "true"}}
|
|
219
|
-
response.setContent(datagzip_{{this.dataname}}, {{this.lengthGzip}});
|
|
220
|
-
{{/case}}
|
|
221
|
-
{{#case "false"}}
|
|
222
|
-
response.setContent(data_{{this.dataname}}, {{this.length}});
|
|
223
|
-
{{/case}}
|
|
224
|
-
{{#case "compiler"}}
|
|
225
|
-
#ifdef {{../definePrefix}}_ENABLE_GZIP
|
|
226
|
-
response.setContent(datagzip_{{this.dataname}}, {{this.lengthGzip}});
|
|
227
|
-
#else
|
|
228
|
-
response.setContent(data_{{this.dataname}}, {{this.length}});
|
|
229
|
-
#endif
|
|
230
|
-
{{/case}}
|
|
231
|
-
{{/switch}}
|
|
232
|
-
|
|
233
|
-
{{../definePrefix}}_onFileServed("{{../basePath}}/{{this.filename}}", 200);
|
|
234
|
-
return response.send();
|
|
235
|
-
});
|
|
236
|
-
{{#if this.isDefault}}{{#if ../basePath}}
|
|
237
|
-
//
|
|
238
|
-
// {{this.filename}} (base path route)
|
|
239
|
-
server->on("{{../basePath}}", HTTP_GET, [](PsychicRequest * request) {
|
|
240
|
-
|
|
241
|
-
{{#switch ../etag}}
|
|
242
|
-
{{#case "true"}}
|
|
243
|
-
if (request->hasHeader("If-None-Match") && request->header("If-None-Match").equals(etag_{{this.dataname}})) {
|
|
244
|
-
PsychicResponse response304(request);
|
|
245
|
-
response304.setCode(304);
|
|
246
|
-
{{../definePrefix}}_onFileServed("{{../basePath}}", 304);
|
|
247
|
-
return response304.send();
|
|
248
|
-
}
|
|
249
|
-
{{/case}}
|
|
250
|
-
{{#case "compiler"}}
|
|
251
|
-
#ifdef {{../definePrefix}}_ENABLE_ETAG
|
|
252
|
-
if (request->hasHeader("If-None-Match") && request->header("If-None-Match").equals(etag_{{this.dataname}})) {
|
|
253
|
-
PsychicResponse response304(request);
|
|
254
|
-
response304.setCode(304);
|
|
255
|
-
{{../definePrefix}}_onFileServed("{{../basePath}}", 304);
|
|
256
|
-
return response304.send();
|
|
257
|
-
}
|
|
258
|
-
#endif
|
|
259
|
-
{{/case}}
|
|
260
|
-
{{/switch}}
|
|
261
|
-
|
|
262
|
-
PsychicResponse response(request);
|
|
263
|
-
response.setContentType("{{this.mime}}");
|
|
264
|
-
|
|
265
|
-
{{#switch ../gzip}}
|
|
266
|
-
{{#case "true"}}
|
|
267
|
-
{{#if this.isGzip}}
|
|
268
|
-
response.addHeader("Content-Encoding", "gzip");
|
|
269
|
-
{{/if}}
|
|
270
|
-
{{/case}}
|
|
271
|
-
{{#case "compiler"}}
|
|
272
|
-
{{#if this.isGzip}}
|
|
273
|
-
#ifdef {{../definePrefix}}_ENABLE_GZIP
|
|
274
|
-
response.addHeader("Content-Encoding", "gzip");
|
|
275
|
-
#endif
|
|
276
|
-
{{/if}}
|
|
277
|
-
{{/case}}
|
|
278
|
-
{{/switch}}
|
|
279
|
-
|
|
280
|
-
{{#switch ../etag}}
|
|
281
|
-
{{#case "true"}}
|
|
282
|
-
{{#../cacheTime}}
|
|
283
|
-
response.addHeader("Cache-Control", "max-age={{value}}");
|
|
284
|
-
{{/../cacheTime}}
|
|
285
|
-
{{^../cacheTime}}
|
|
286
|
-
response.addHeader("Cache-Control", "no-cache");
|
|
287
|
-
{{/../cacheTime}}
|
|
288
|
-
response.addHeader("ETag", etag_{{this.dataname}});
|
|
289
|
-
{{/case}}
|
|
290
|
-
{{#case "compiler"}}
|
|
291
|
-
#ifdef {{../definePrefix}}_ENABLE_ETAG
|
|
292
|
-
{{#../cacheTime}}
|
|
293
|
-
response.addHeader("Cache-Control", "max-age={{value}}");
|
|
294
|
-
{{/../cacheTime}}
|
|
295
|
-
{{^../cacheTime}}
|
|
296
|
-
response.addHeader("Cache-Control", "no-cache");
|
|
297
|
-
{{/../cacheTime}}
|
|
298
|
-
response.addHeader("ETag", etag_{{this.dataname}});
|
|
299
|
-
#endif
|
|
300
|
-
{{/case}}
|
|
301
|
-
{{/switch}}
|
|
302
|
-
|
|
303
|
-
{{#switch ../gzip}}
|
|
304
|
-
{{#case "true"}}
|
|
305
|
-
response.setContent(datagzip_{{this.dataname}}, {{this.lengthGzip}});
|
|
306
|
-
{{/case}}
|
|
307
|
-
{{#case "false"}}
|
|
308
|
-
response.setContent(data_{{this.dataname}}, {{this.length}});
|
|
309
|
-
{{/case}}
|
|
310
|
-
{{#case "compiler"}}
|
|
311
|
-
#ifdef {{../definePrefix}}_ENABLE_GZIP
|
|
312
|
-
response.setContent(datagzip_{{this.dataname}}, {{this.lengthGzip}});
|
|
313
|
-
#else
|
|
314
|
-
response.setContent(data_{{this.dataname}}, {{this.length}});
|
|
315
|
-
#endif
|
|
316
|
-
{{/case}}
|
|
317
|
-
{{/switch}}
|
|
318
|
-
|
|
319
|
-
{{../definePrefix}}_onFileServed("{{../basePath}}", 200);
|
|
320
|
-
return response.send();
|
|
321
|
-
});
|
|
322
|
-
{{/if}}{{/if}}
|
|
323
|
-
|
|
324
|
-
{{/each}}
|
|
325
|
-
}`;
|
|
326
|
-
const psychic2Template = `
|
|
327
|
-
//engine: PsychicHttpServerV2
|
|
328
|
-
//config: {{{config}}}
|
|
329
123
|
{{#if created }}
|
|
330
124
|
//created: {{now}}
|
|
331
125
|
{{/if}}
|
|
@@ -704,21 +498,29 @@ const getTemplate = (engine) => {
|
|
|
704
498
|
switch (engine) {
|
|
705
499
|
case 'psychic':
|
|
706
500
|
return psychicTemplate;
|
|
707
|
-
case '
|
|
708
|
-
return
|
|
501
|
+
case 'async':
|
|
502
|
+
return asyncTemplate;
|
|
709
503
|
case 'espidf':
|
|
710
504
|
return cppCodeEspIdf_1.espidfTemplate;
|
|
711
505
|
default:
|
|
712
|
-
|
|
506
|
+
throw new Error(`Unknown engine: ${engine}`);
|
|
713
507
|
}
|
|
714
508
|
};
|
|
509
|
+
const bufferToByteString = (buffer) => {
|
|
510
|
+
if (buffer.length === 0)
|
|
511
|
+
return '';
|
|
512
|
+
let result = buffer[0].toString(10);
|
|
513
|
+
for (let index = 1; index < buffer.length; index++)
|
|
514
|
+
result += ',' + buffer[index].toString(10);
|
|
515
|
+
return result;
|
|
516
|
+
};
|
|
715
517
|
const transformSourceToTemplateData = (s, etag) => ({
|
|
716
518
|
...s,
|
|
717
519
|
length: s.content.length,
|
|
718
|
-
bytes:
|
|
520
|
+
bytes: bufferToByteString(s.content),
|
|
719
521
|
lengthGzip: s.contentGzip.length,
|
|
720
|
-
bytesGzip:
|
|
721
|
-
isDefault: s.filename.
|
|
522
|
+
bytesGzip: bufferToByteString(s.contentGzip),
|
|
523
|
+
isDefault: s.filename === 'index.html' || s.filename === 'index.htm',
|
|
722
524
|
gzipSizeForManifest: s.isGzip ? s.contentGzip.length : 0,
|
|
723
525
|
etagForManifest: etag === 'false' ? 'NULL' : `etag_${s.dataname}`
|
|
724
526
|
});
|
|
@@ -728,7 +530,7 @@ const postProcessCppCode = (code) => code
|
|
|
728
530
|
.filter(Boolean)
|
|
729
531
|
.map((line) => (line === '//' ? '' : line))
|
|
730
532
|
.join('\n')
|
|
731
|
-
.replace(
|
|
533
|
+
.replace(/\n{2,}/g, '\n');
|
|
732
534
|
const createHandlebarsHelpers = () => {
|
|
733
535
|
let switchValue;
|
|
734
536
|
return {
|
|
@@ -752,7 +554,10 @@ const getCppCode = (sources, filesByExtension) => {
|
|
|
752
554
|
const template = (0, handlebars_1.compile)(getTemplate(commandLine_1.cmdLine.engine));
|
|
753
555
|
const templateData = {
|
|
754
556
|
config: (0, commandLine_1.formatConfiguration)(commandLine_1.cmdLine),
|
|
755
|
-
now:
|
|
557
|
+
now: (() => {
|
|
558
|
+
const d = new Date();
|
|
559
|
+
return `${d.toLocaleDateString()} ${d.toLocaleTimeString()}`;
|
|
560
|
+
})(),
|
|
756
561
|
fileCount: sources.length.toString(),
|
|
757
562
|
fileSize: sources.reduce((previous, current) => previous + current.content.length, 0).toString(),
|
|
758
563
|
fileGzipSize: sources.reduce((previous, current) => previous + current.contentGzip.length, 0).toString(),
|
package/dist/cppCodeEspIdf.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const espidfTemplate = "\n//engine: espidf\n//config: {{{config}}}\n{{#if created }}\n//created: {{now}}\n{{/if}}\n//\n\n{{#switch etag}}\n{{#case \"true\"}}\n#ifdef {{definePrefix}}_ENABLE_ETAG\n#warning {{definePrefix}}_ENABLE_ETAG has no effect because it is permanently switched ON\n#endif\n{{/case}}\n{{#case \"false\"}}\n#ifdef {{definePrefix}}_ENABLE_ETAG\n#warning {{definePrefix}}_ENABLE_ETAG has no effect because it is permanently switched OFF\n#endif\n{{/case}}\n{{/switch}}\n\n{{#switch gzip}}\n{{#case \"true\"}}\n#ifdef {{definePrefix}}_ENABLE_GZIP\n#warning {{definePrefix}}_ENABLE_GZIP has no effect because it is permanently switched ON\n#endif\n{{/case}}\n{{#case \"false\"}}\n#ifdef {{definePrefix}}_ENABLE_GZIP\n#warning {{definePrefix}}_ENABLE_GZIP has no effect because it is permanently switched OFF\n#endif\n{{/case}}\n{{/switch}}\n\n//\n{{#if version }}\n#define {{definePrefix}}_VERSION \"{{version}}\"\n{{/if}}\n#define {{definePrefix}}_COUNT {{fileCount}}\n#define {{definePrefix}}_SIZE {{fileSize}}\n#define {{definePrefix}}_SIZE_GZIP {{fileGzipSize}}\n\n//\n{{#each sources}}\n#define {{../definePrefix}}_FILE_{{this.datanameUpperCase}}\n{{/each}}\n\n//\n{{#each filesByExtension}}\n#define {{../definePrefix}}_{{this.extension}}_FILES {{this.count}}\n{{/each}}\n\n#include <stdint.h>\n#include <string.h>\n#include <stdlib.h>\n#include <esp_err.h>\n#include <esp_http_server.h>\n\n//\n{{#switch gzip}}\n{{#case \"true\"}}\n {{#each sources}}\nconst char datagzip_{{this.dataname}}[{{this.lengthGzip}}] = { {{this.bytesGzip}} };\n {{/each}}\n{{/case}}\n{{#case \"false\"}}\n {{#each sources}}\nconst char data_{{this.dataname}}[{{this.length}}] = { {{this.bytes}} };\n {{/each}}\n{{/case}}\n{{#case \"compiler\"}}\n#ifdef {{definePrefix}}_ENABLE_GZIP\n {{#each sources}}\nconst char datagzip_{{this.dataname}}[{{this.lengthGzip}}] = { {{this.bytesGzip}} };\n {{/each}}\n#else\n {{#each sources}}\nconst char data_{{this.dataname}}[{{this.length}}] = { {{this.bytes}} };\n {{/each}}\n#endif \n{{/case}}\n{{/switch}}\n\n//\n{{#switch etag}}\n{{#case \"true\"}}\n {{#each sources}}\nstatic const char etag_{{this.dataname}}[] = \"{{this.sha256}}\";\n {{/each}}\n{{/case}}\n{{#case \"false\"}}\n{{/case}}\n{{#case \"compiler\"}}\n#ifdef {{definePrefix}}_ENABLE_ETAG\n {{#each sources}}\nstatic const char etag_{{this.dataname}}[] = \"{{this.sha256}}\";\n {{/each}}\n#endif\n{{/case}}\n{{/switch}}\n\n// File manifest struct (C-compatible typedef)\ntypedef struct {\n const char* path;\n uint32_t size;\n uint32_t gzipSize;\n const char* etag;\n const char* contentType;\n} {{definePrefix}}_FileInfo;\n\n// File manifest array\nstatic const {{definePrefix}}_FileInfo {{definePrefix}}_FILES[] = {\n{{#each sources}}\n { \"{{../basePath}}/{{this.filename}}\", {{this.length}}, {{this.gzipSizeForManifest}}, {{this.etagForManifest}}, \"{{this.mime}}\" },\n{{/each}}\n};\nstatic const size_t {{definePrefix}}_FILE_COUNT = sizeof({{definePrefix}}_FILES) / sizeof({{definePrefix}}_FILES[0]);\n\n// File served hook - override with your own implementation\n__attribute__((weak)) void {{definePrefix}}_onFileServed(const char* path, int statusCode) {}\n\n{{#each sources}}\n\nstatic esp_err_t file_handler_{{this.datanameUpperCase}} (httpd_req_t *req)\n{\n{{#switch ../etag}}\n{{#case \"true\"}}\n size_t hdr_len = httpd_req_get_hdr_value_len(req, \"If-None-Match\");\n if (hdr_len > 0) {\n char* hdr_value = malloc(hdr_len + 1);\n if (httpd_req_get_hdr_value_str(req, \"If-None-Match\", hdr_value, hdr_len + 1) == ESP_OK) {\n if (strcmp(hdr_value, etag_{{this.dataname}}) == 0) {\n free(hdr_value);\n httpd_resp_set_status(req, \"304 Not Modified\");\n {{../definePrefix}}_onFileServed(\"{{../basePath}}/{{this.filename}}\", 304);\n httpd_resp_send(req, NULL, 0);\n return ESP_OK;\n }\n }\n free(hdr_value);\n }\n{{/case}}\n{{#case \"compiler\"}}\n #ifdef {{../definePrefix}}_ENABLE_ETAG\n size_t hdr_len = httpd_req_get_hdr_value_len(req, \"If-None-Match\");\n if (hdr_len > 0) {\n char* hdr_value = malloc(hdr_len + 1);\n if (httpd_req_get_hdr_value_str(req, \"If-None-Match\", hdr_value, hdr_len + 1) == ESP_OK) {\n if (strcmp(hdr_value, etag_{{this.dataname}}) == 0) {\n free(hdr_value);\n httpd_resp_set_status(req, \"304 Not Modified\");\n {{../definePrefix}}_onFileServed(\"{{../basePath}}/{{this.filename}}\", 304);\n httpd_resp_send(req, NULL, 0);\n return ESP_OK;\n }\n }\n free(hdr_value);\n }\n #endif\n{{/case}}\n{{/switch}}\n httpd_resp_set_type(req, \"{{this.mime}}\");\n{{#switch ../gzip}}\n{{#case \"true\"}}\n{{#if this.isGzip}}\n httpd_resp_set_hdr(req, \"Content-Encoding\", \"gzip\");\n{{/if}}\n{{/case}}\n{{#case \"compiler\"}}\n {{#if this.isGzip}}\n #ifdef {{../definePrefix}}_ENABLE_GZIP\n httpd_resp_set_hdr(req, \"Content-Encoding\", \"gzip\");\n #endif \n {{/if}}\n{{/case}}\n{{/switch}}\n\n{{#switch ../etag}}\n{{#case \"true\"}}\n{{#../cacheTime}}\n httpd_resp_set_hdr(req, \"Cache-Control\", \"max-age={{value}}\");\n{{/../cacheTime}}\n{{^../cacheTime}}\n httpd_resp_set_hdr(req, \"Cache-Control\", \"no-cache\");\n{{/../cacheTime}}\n httpd_resp_set_hdr(req, \"ETag\", etag_{{this.dataname}});\n{{/case}}\n{{#case \"compiler\"}}\n #ifdef {{../definePrefix}}_ENABLE_ETAG\n{{#../cacheTime}}\n httpd_resp_set_hdr(req, \"Cache-Control\", \"max-age={{value}}\");\n{{/../cacheTime}}\n{{^../cacheTime}}\n httpd_resp_set_hdr(req, \"Cache-Control\", \"no-cache\");\n{{/../cacheTime}}\n httpd_resp_set_hdr(req, \"ETag\", etag_{{this.dataname}});\n #endif \n{{/case}}\n{{/switch}}\n\n{{#switch ../gzip}}\n{{#case \"true\"}}\n {{../definePrefix}}_onFileServed(\"{{../basePath}}/{{this.filename}}\", 200);\n httpd_resp_send(req, datagzip_{{this.dataname}}, {{this.lengthGzip}});\n{{/case}}\n{{#case \"false\"}}\n {{../definePrefix}}_onFileServed(\"{{../basePath}}/{{this.filename}}\", 200);\n httpd_resp_send(req, data_{{this.dataname}}, {{this.length}});\n{{/case}}\n{{#case \"compiler\"}}\n {{../definePrefix}}_onFileServed(\"{{../basePath}}/{{this.filename}}\", 200);\n #ifdef {{../definePrefix}}_ENABLE_GZIP\n httpd_resp_send(req, datagzip_{{this.dataname}}, {{this.lengthGzip}});\n #else\n httpd_resp_send(req, data_{{this.dataname}}, {{this.length}});\n #endif\n{{/case}}\n{{/switch}}\n return ESP_OK;\n}\n\n{{#if this.isDefault}}\nstatic const httpd_uri_t route_def_{{this.datanameUpperCase}} = {\n .uri = \"{{#if ../basePath}}{{../basePath}}{{else}}/{{/if}}\",\n .method = HTTP_GET,\n .handler = file_handler_{{this.datanameUpperCase}},\n};\n{{/if}}\n\nstatic const httpd_uri_t route_{{this.datanameUpperCase}} = {\n .uri = \"{{../basePath}}/{{this.filename}}\",\n .method = HTTP_GET,\n .handler = file_handler_{{this.datanameUpperCase}},\n};\n\n{{/each}}\n\n\n\nstatic inline void {{methodName}}(httpd_handle_t server) {\n{{#each sources}}\n{{#if this.isDefault}}\n httpd_register_uri_handler(server, &route_def_{{this.datanameUpperCase}});\n{{/if}}\n httpd_register_uri_handler(server, &route_{{this.datanameUpperCase}});\n{{/each}}\n\n}";
|
|
1
|
+
export declare const espidfTemplate = "\n//engine: espidf\n//config: {{{config}}}\n{{#if created }}\n//created: {{now}}\n{{/if}}\n//\n\n{{#switch etag}}\n{{#case \"true\"}}\n#ifdef {{definePrefix}}_ENABLE_ETAG\n#warning {{definePrefix}}_ENABLE_ETAG has no effect because it is permanently switched ON\n#endif\n{{/case}}\n{{#case \"false\"}}\n#ifdef {{definePrefix}}_ENABLE_ETAG\n#warning {{definePrefix}}_ENABLE_ETAG has no effect because it is permanently switched OFF\n#endif\n{{/case}}\n{{/switch}}\n\n{{#switch gzip}}\n{{#case \"true\"}}\n#ifdef {{definePrefix}}_ENABLE_GZIP\n#warning {{definePrefix}}_ENABLE_GZIP has no effect because it is permanently switched ON\n#endif\n{{/case}}\n{{#case \"false\"}}\n#ifdef {{definePrefix}}_ENABLE_GZIP\n#warning {{definePrefix}}_ENABLE_GZIP has no effect because it is permanently switched OFF\n#endif\n{{/case}}\n{{/switch}}\n\n//\n{{#if version }}\n#define {{definePrefix}}_VERSION \"{{version}}\"\n{{/if}}\n#define {{definePrefix}}_COUNT {{fileCount}}\n#define {{definePrefix}}_SIZE {{fileSize}}\n#define {{definePrefix}}_SIZE_GZIP {{fileGzipSize}}\n\n//\n{{#each sources}}\n#define {{../definePrefix}}_FILE_{{this.datanameUpperCase}}\n{{/each}}\n\n//\n{{#each filesByExtension}}\n#define {{../definePrefix}}_{{this.extension}}_FILES {{this.count}}\n{{/each}}\n\n#include <stdint.h>\n#include <string.h>\n#include <stdlib.h>\n#include <esp_err.h>\n#include <esp_http_server.h>\n\n//\n{{#switch gzip}}\n{{#case \"true\"}}\n {{#each sources}}\nconst unsigned char datagzip_{{this.dataname}}[{{this.lengthGzip}}] = { {{this.bytesGzip}} };\n {{/each}}\n{{/case}}\n{{#case \"false\"}}\n {{#each sources}}\nconst unsigned char data_{{this.dataname}}[{{this.length}}] = { {{this.bytes}} };\n {{/each}}\n{{/case}}\n{{#case \"compiler\"}}\n#ifdef {{definePrefix}}_ENABLE_GZIP\n {{#each sources}}\nconst unsigned char datagzip_{{this.dataname}}[{{this.lengthGzip}}] = { {{this.bytesGzip}} };\n {{/each}}\n#else\n {{#each sources}}\nconst unsigned char data_{{this.dataname}}[{{this.length}}] = { {{this.bytes}} };\n {{/each}}\n#endif \n{{/case}}\n{{/switch}}\n\n//\n{{#switch etag}}\n{{#case \"true\"}}\n {{#each sources}}\nstatic const char etag_{{this.dataname}}[] = \"{{this.sha256}}\";\n {{/each}}\n{{/case}}\n{{#case \"false\"}}\n{{/case}}\n{{#case \"compiler\"}}\n#ifdef {{definePrefix}}_ENABLE_ETAG\n {{#each sources}}\nstatic const char etag_{{this.dataname}}[] = \"{{this.sha256}}\";\n {{/each}}\n#endif\n{{/case}}\n{{/switch}}\n\n// File manifest struct (C-compatible typedef)\ntypedef struct {\n const char* path;\n uint32_t size;\n uint32_t gzipSize;\n const char* etag;\n const char* contentType;\n} {{definePrefix}}_FileInfo;\n\n// File manifest array\nstatic const {{definePrefix}}_FileInfo {{definePrefix}}_FILES[] = {\n{{#each sources}}\n { \"{{../basePath}}/{{this.filename}}\", {{this.length}}, {{this.gzipSizeForManifest}}, {{this.etagForManifest}}, \"{{this.mime}}\" },\n{{/each}}\n};\nstatic const size_t {{definePrefix}}_FILE_COUNT = sizeof({{definePrefix}}_FILES) / sizeof({{definePrefix}}_FILES[0]);\n\n// File served hook - override with your own implementation\n__attribute__((weak)) void {{definePrefix}}_onFileServed(const char* path, int statusCode) {}\n\n{{#each sources}}\n\nstatic esp_err_t file_handler_{{this.datanameUpperCase}} (httpd_req_t *req)\n{\n{{#switch ../etag}}\n{{#case \"true\"}}\n size_t hdr_len = httpd_req_get_hdr_value_len(req, \"If-None-Match\");\n if (hdr_len > 0) {\n char* hdr_value = malloc(hdr_len + 1);\n if (hdr_value == NULL) { httpd_resp_send_500(req); return ESP_FAIL; }\n if (httpd_req_get_hdr_value_str(req, \"If-None-Match\", hdr_value, hdr_len + 1) == ESP_OK) {\n if (strcmp(hdr_value, etag_{{this.dataname}}) == 0) {\n free(hdr_value);\n httpd_resp_set_status(req, \"304 Not Modified\");\n {{../definePrefix}}_onFileServed(\"{{../basePath}}/{{this.filename}}\", 304);\n httpd_resp_send(req, NULL, 0);\n return ESP_OK;\n }\n }\n free(hdr_value);\n }\n{{/case}}\n{{#case \"compiler\"}}\n #ifdef {{../definePrefix}}_ENABLE_ETAG\n size_t hdr_len = httpd_req_get_hdr_value_len(req, \"If-None-Match\");\n if (hdr_len > 0) {\n char* hdr_value = malloc(hdr_len + 1);\n if (hdr_value == NULL) { httpd_resp_send_500(req); return ESP_FAIL; }\n if (httpd_req_get_hdr_value_str(req, \"If-None-Match\", hdr_value, hdr_len + 1) == ESP_OK) {\n if (strcmp(hdr_value, etag_{{this.dataname}}) == 0) {\n free(hdr_value);\n httpd_resp_set_status(req, \"304 Not Modified\");\n {{../definePrefix}}_onFileServed(\"{{../basePath}}/{{this.filename}}\", 304);\n httpd_resp_send(req, NULL, 0);\n return ESP_OK;\n }\n }\n free(hdr_value);\n }\n #endif\n{{/case}}\n{{/switch}}\n httpd_resp_set_type(req, \"{{this.mime}}\");\n{{#switch ../gzip}}\n{{#case \"true\"}}\n{{#if this.isGzip}}\n httpd_resp_set_hdr(req, \"Content-Encoding\", \"gzip\");\n{{/if}}\n{{/case}}\n{{#case \"compiler\"}}\n {{#if this.isGzip}}\n #ifdef {{../definePrefix}}_ENABLE_GZIP\n httpd_resp_set_hdr(req, \"Content-Encoding\", \"gzip\");\n #endif \n {{/if}}\n{{/case}}\n{{/switch}}\n\n{{#switch ../etag}}\n{{#case \"true\"}}\n{{#../cacheTime}}\n httpd_resp_set_hdr(req, \"Cache-Control\", \"max-age={{value}}\");\n{{/../cacheTime}}\n{{^../cacheTime}}\n httpd_resp_set_hdr(req, \"Cache-Control\", \"no-cache\");\n{{/../cacheTime}}\n httpd_resp_set_hdr(req, \"ETag\", etag_{{this.dataname}});\n{{/case}}\n{{#case \"compiler\"}}\n #ifdef {{../definePrefix}}_ENABLE_ETAG\n{{#../cacheTime}}\n httpd_resp_set_hdr(req, \"Cache-Control\", \"max-age={{value}}\");\n{{/../cacheTime}}\n{{^../cacheTime}}\n httpd_resp_set_hdr(req, \"Cache-Control\", \"no-cache\");\n{{/../cacheTime}}\n httpd_resp_set_hdr(req, \"ETag\", etag_{{this.dataname}});\n #endif \n{{/case}}\n{{/switch}}\n\n{{#switch ../gzip}}\n{{#case \"true\"}}\n {{../definePrefix}}_onFileServed(\"{{../basePath}}/{{this.filename}}\", 200);\n httpd_resp_send(req, (const char *)datagzip_{{this.dataname}}, {{this.lengthGzip}});\n{{/case}}\n{{#case \"false\"}}\n {{../definePrefix}}_onFileServed(\"{{../basePath}}/{{this.filename}}\", 200);\n httpd_resp_send(req, (const char *)data_{{this.dataname}}, {{this.length}});\n{{/case}}\n{{#case \"compiler\"}}\n {{../definePrefix}}_onFileServed(\"{{../basePath}}/{{this.filename}}\", 200);\n #ifdef {{../definePrefix}}_ENABLE_GZIP\n httpd_resp_send(req, (const char *)datagzip_{{this.dataname}}, {{this.lengthGzip}});\n #else\n httpd_resp_send(req, (const char *)data_{{this.dataname}}, {{this.length}});\n #endif\n{{/case}}\n{{/switch}}\n return ESP_OK;\n}\n\n{{#if this.isDefault}}\nstatic const httpd_uri_t route_def_{{this.datanameUpperCase}} = {\n .uri = \"{{#if ../basePath}}{{../basePath}}{{else}}/{{/if}}\",\n .method = HTTP_GET,\n .handler = file_handler_{{this.datanameUpperCase}},\n};\n{{/if}}\n\nstatic const httpd_uri_t route_{{this.datanameUpperCase}} = {\n .uri = \"{{../basePath}}/{{this.filename}}\",\n .method = HTTP_GET,\n .handler = file_handler_{{this.datanameUpperCase}},\n};\n\n{{/each}}\n\n\n\nstatic inline void {{methodName}}(httpd_handle_t server) {\n{{#each sources}}\n{{#if this.isDefault}}\n httpd_register_uri_handler(server, &route_def_{{this.datanameUpperCase}});\n{{/if}}\n httpd_register_uri_handler(server, &route_{{this.datanameUpperCase}});\n{{/each}}\n\n}";
|
package/dist/cppCodeEspIdf.js
CHANGED
|
@@ -63,22 +63,22 @@ exports.espidfTemplate = `
|
|
|
63
63
|
{{#switch gzip}}
|
|
64
64
|
{{#case "true"}}
|
|
65
65
|
{{#each sources}}
|
|
66
|
-
const char datagzip_{{this.dataname}}[{{this.lengthGzip}}] = { {{this.bytesGzip}} };
|
|
66
|
+
const unsigned char datagzip_{{this.dataname}}[{{this.lengthGzip}}] = { {{this.bytesGzip}} };
|
|
67
67
|
{{/each}}
|
|
68
68
|
{{/case}}
|
|
69
69
|
{{#case "false"}}
|
|
70
70
|
{{#each sources}}
|
|
71
|
-
const char data_{{this.dataname}}[{{this.length}}] = { {{this.bytes}} };
|
|
71
|
+
const unsigned char data_{{this.dataname}}[{{this.length}}] = { {{this.bytes}} };
|
|
72
72
|
{{/each}}
|
|
73
73
|
{{/case}}
|
|
74
74
|
{{#case "compiler"}}
|
|
75
75
|
#ifdef {{definePrefix}}_ENABLE_GZIP
|
|
76
76
|
{{#each sources}}
|
|
77
|
-
const char datagzip_{{this.dataname}}[{{this.lengthGzip}}] = { {{this.bytesGzip}} };
|
|
77
|
+
const unsigned char datagzip_{{this.dataname}}[{{this.lengthGzip}}] = { {{this.bytesGzip}} };
|
|
78
78
|
{{/each}}
|
|
79
79
|
#else
|
|
80
80
|
{{#each sources}}
|
|
81
|
-
const char data_{{this.dataname}}[{{this.length}}] = { {{this.bytes}} };
|
|
81
|
+
const unsigned char data_{{this.dataname}}[{{this.length}}] = { {{this.bytes}} };
|
|
82
82
|
{{/each}}
|
|
83
83
|
#endif
|
|
84
84
|
{{/case}}
|
|
@@ -131,6 +131,7 @@ static esp_err_t file_handler_{{this.datanameUpperCase}} (httpd_req_t *req)
|
|
|
131
131
|
size_t hdr_len = httpd_req_get_hdr_value_len(req, "If-None-Match");
|
|
132
132
|
if (hdr_len > 0) {
|
|
133
133
|
char* hdr_value = malloc(hdr_len + 1);
|
|
134
|
+
if (hdr_value == NULL) { httpd_resp_send_500(req); return ESP_FAIL; }
|
|
134
135
|
if (httpd_req_get_hdr_value_str(req, "If-None-Match", hdr_value, hdr_len + 1) == ESP_OK) {
|
|
135
136
|
if (strcmp(hdr_value, etag_{{this.dataname}}) == 0) {
|
|
136
137
|
free(hdr_value);
|
|
@@ -148,6 +149,7 @@ static esp_err_t file_handler_{{this.datanameUpperCase}} (httpd_req_t *req)
|
|
|
148
149
|
size_t hdr_len = httpd_req_get_hdr_value_len(req, "If-None-Match");
|
|
149
150
|
if (hdr_len > 0) {
|
|
150
151
|
char* hdr_value = malloc(hdr_len + 1);
|
|
152
|
+
if (hdr_value == NULL) { httpd_resp_send_500(req); return ESP_FAIL; }
|
|
151
153
|
if (httpd_req_get_hdr_value_str(req, "If-None-Match", hdr_value, hdr_len + 1) == ESP_OK) {
|
|
152
154
|
if (strcmp(hdr_value, etag_{{this.dataname}}) == 0) {
|
|
153
155
|
free(hdr_value);
|
|
@@ -204,18 +206,18 @@ static esp_err_t file_handler_{{this.datanameUpperCase}} (httpd_req_t *req)
|
|
|
204
206
|
{{#switch ../gzip}}
|
|
205
207
|
{{#case "true"}}
|
|
206
208
|
{{../definePrefix}}_onFileServed("{{../basePath}}/{{this.filename}}", 200);
|
|
207
|
-
httpd_resp_send(req, datagzip_{{this.dataname}}, {{this.lengthGzip}});
|
|
209
|
+
httpd_resp_send(req, (const char *)datagzip_{{this.dataname}}, {{this.lengthGzip}});
|
|
208
210
|
{{/case}}
|
|
209
211
|
{{#case "false"}}
|
|
210
212
|
{{../definePrefix}}_onFileServed("{{../basePath}}/{{this.filename}}", 200);
|
|
211
|
-
httpd_resp_send(req, data_{{this.dataname}}, {{this.length}});
|
|
213
|
+
httpd_resp_send(req, (const char *)data_{{this.dataname}}, {{this.length}});
|
|
212
214
|
{{/case}}
|
|
213
215
|
{{#case "compiler"}}
|
|
214
216
|
{{../definePrefix}}_onFileServed("{{../basePath}}/{{this.filename}}", 200);
|
|
215
217
|
#ifdef {{../definePrefix}}_ENABLE_GZIP
|
|
216
|
-
httpd_resp_send(req, datagzip_{{this.dataname}}, {{this.lengthGzip}});
|
|
218
|
+
httpd_resp_send(req, (const char *)datagzip_{{this.dataname}}, {{this.lengthGzip}});
|
|
217
219
|
#else
|
|
218
|
-
httpd_resp_send(req, data_{{this.dataname}}, {{this.length}});
|
|
220
|
+
httpd_resp_send(req, (const char *)data_{{this.dataname}}, {{this.length}});
|
|
219
221
|
#endif
|
|
220
222
|
{{/case}}
|
|
221
223
|
{{/switch}}
|
package/dist/errorMessages.d.ts
CHANGED
|
@@ -2,4 +2,4 @@ export declare function getMissingIndexError(engine: string): string;
|
|
|
2
2
|
export declare function getInvalidEngineError(attempted: string): string;
|
|
3
3
|
export declare function getSourcepathNotFoundError(sourcepath: string, reason: 'not_found' | 'not_directory'): string;
|
|
4
4
|
export declare function getSizeBudgetExceededError(type: 'size' | 'gzipSize', limit: number, actual: number): string;
|
|
5
|
-
export declare function getMaxUriHandlersHint(engine: string, routeCount: number): string;
|
|
5
|
+
export declare function getMaxUriHandlersHint(engine: string, routeCount: number, espmethod?: string): string;
|
package/dist/errorMessages.js
CHANGED
|
@@ -13,7 +13,6 @@ const consoleColor_1 = require("./consoleColor");
|
|
|
13
13
|
function getEngineName(engine) {
|
|
14
14
|
const names = {
|
|
15
15
|
psychic: 'PsychicHttpServer',
|
|
16
|
-
psychic2: 'PsychicHttpServer V2',
|
|
17
16
|
async: 'ESPAsyncWebServer',
|
|
18
17
|
espidf: 'ESP-IDF'
|
|
19
18
|
};
|
|
@@ -24,9 +23,6 @@ function getMissingIndexError(engine) {
|
|
|
24
23
|
psychic: ` 1. Add an index.html file to your source directory
|
|
25
24
|
2. The file will automatically be set as the default route ("/")
|
|
26
25
|
3. PsychicHttpServer uses: server->defaultEndpoint = ...`,
|
|
27
|
-
psychic2: ` 1. Add an index.html file to your source directory
|
|
28
|
-
2. The file will automatically be set as the default route ("/")
|
|
29
|
-
3. PsychicHttpServer V2 uses: server->defaultEndpoint = ...`,
|
|
30
26
|
async: ` 1. Add an index.html file to your source directory
|
|
31
27
|
2. The file will automatically create a "/" route handler
|
|
32
28
|
3. ESPAsyncWebServer uses: server.on("/", HTTP_GET, ...)`,
|
|
@@ -55,7 +51,6 @@ function getInvalidEngineError(attempted) {
|
|
|
55
51
|
|
|
56
52
|
Valid engines are:
|
|
57
53
|
${(0, consoleColor_1.cyanLog)('• psychic')} - PsychicHttpServer (ESP32 only, fastest performance)
|
|
58
|
-
${(0, consoleColor_1.cyanLog)('• psychic2')} - PsychicHttpServer V2 (ESP32 only, modern API)
|
|
59
54
|
${(0, consoleColor_1.cyanLog)('• async')} - ESPAsyncWebServer (ESP32/ESP8266 compatible)
|
|
60
55
|
${(0, consoleColor_1.cyanLog)('• espidf')} - Native ESP-IDF web server (ESP32 only, no Arduino)
|
|
61
56
|
|
|
@@ -136,22 +131,18 @@ CI integration:
|
|
|
136
131
|
This non-zero exit code allows build pipelines to fail early when
|
|
137
132
|
the frontend exceeds allocated flash space.`);
|
|
138
133
|
}
|
|
139
|
-
function getMaxUriHandlersHint(engine, routeCount) {
|
|
134
|
+
function getMaxUriHandlersHint(engine, routeCount, espmethod = 'initSvelteStaticFiles') {
|
|
140
135
|
const recommended = routeCount + 5;
|
|
141
136
|
const hints = {
|
|
142
137
|
psychic: `PsychicHttpServer server;
|
|
143
138
|
server.config.max_uri_handlers = ${recommended}; // Default is 8, you need at least ${routeCount}
|
|
144
|
-
|
|
145
|
-
server.listen(80);`,
|
|
146
|
-
psychic2: `PsychicHttpServer server;
|
|
147
|
-
server.config.max_uri_handlers = ${recommended}; // Default is 8, you need at least ${routeCount}
|
|
148
|
-
initSvelteStaticFiles(&server);
|
|
139
|
+
${espmethod}(&server);
|
|
149
140
|
server.listen(80);`,
|
|
150
141
|
espidf: `httpd_config_t config = HTTPD_DEFAULT_CONFIG();
|
|
151
142
|
config.max_uri_handlers = ${recommended}; // Default is 8, you need at least ${routeCount}
|
|
152
143
|
httpd_handle_t server = NULL;
|
|
153
144
|
httpd_start(&server, &config);
|
|
154
|
-
|
|
145
|
+
${espmethod}(server);`
|
|
155
146
|
};
|
|
156
147
|
const hint = hints[engine];
|
|
157
148
|
if (!hint)
|
package/dist/file.d.ts
CHANGED
package/dist/file.js
CHANGED
|
@@ -14,13 +14,12 @@ const consoleColor_1 = require("./consoleColor");
|
|
|
14
14
|
const errorMessages_1 = require("./errorMessages");
|
|
15
15
|
const findSimilarFiles = (files) => {
|
|
16
16
|
const contentComparer = new Map();
|
|
17
|
-
for (const [filename,
|
|
18
|
-
const
|
|
19
|
-
const existingFiles = contentComparer.get(hash);
|
|
17
|
+
for (const [filename, fileData] of files.entries()) {
|
|
18
|
+
const existingFiles = contentComparer.get(fileData.hash);
|
|
20
19
|
if (existingFiles)
|
|
21
20
|
existingFiles.push(filename);
|
|
22
21
|
else
|
|
23
|
-
contentComparer.set(hash, [filename]);
|
|
22
|
+
contentComparer.set(fileData.hash, [filename]);
|
|
24
23
|
}
|
|
25
24
|
const result = [];
|
|
26
25
|
for (const filenames of contentComparer.values())
|
|
@@ -30,7 +29,7 @@ const findSimilarFiles = (files) => {
|
|
|
30
29
|
};
|
|
31
30
|
const shouldSkipFile = (filename, allFilenames) => {
|
|
32
31
|
const extension = node_path_1.default.extname(filename);
|
|
33
|
-
const compressedExtensions = ['.gz', '.
|
|
32
|
+
const compressedExtensions = ['.gz', '.brotli', '.br'];
|
|
34
33
|
if (compressedExtensions.includes(extension)) {
|
|
35
34
|
const original = filename.slice(0, -1 * extension.length);
|
|
36
35
|
if (allFilenames.includes(original)) {
|
|
@@ -72,10 +71,14 @@ const getFiles = () => {
|
|
|
72
71
|
console.log((0, consoleColor_1.cyanLog)(`... and ${excludedFiles.length - displayLimit} more`));
|
|
73
72
|
console.log();
|
|
74
73
|
}
|
|
74
|
+
else if (excludePatterns.length > 0)
|
|
75
|
+
console.log((0, consoleColor_1.yellowLog)(`Warning: --exclude patterns matched no files: ${excludePatterns.join(', ')}`));
|
|
75
76
|
const result = new Map();
|
|
76
77
|
for (const filename of filenames) {
|
|
77
78
|
const filePath = node_path_1.default.join(commandLine_1.cmdLine.sourcepath, filename);
|
|
78
|
-
|
|
79
|
+
const content = (0, node_fs_1.readFileSync)(filePath, { flag: 'r' });
|
|
80
|
+
const hash = (0, node_crypto_1.createHash)('sha256').update(content).digest('hex');
|
|
81
|
+
result.set(filename, { content, hash });
|
|
79
82
|
}
|
|
80
83
|
const duplicates = findSimilarFiles(result);
|
|
81
84
|
for (const sameFiles of duplicates)
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import { CppCodeSource } from './cppCode';
|
|
1
|
+
import { CppCodeSource, ExtensionGroups } from './cppCode';
|
|
2
2
|
declare const shouldUseGzip: (originalSize: number, compressedSize: number) => boolean;
|
|
3
3
|
declare const calculateCompressionRatio: (originalSize: number, compressedSize: number) => number;
|
|
4
4
|
declare const formatCompressionLog: (filename: string, padding: string, originalSize: number, compressedSize: number, useGzip: boolean) => string;
|
|
5
|
+
declare const formatSize: (bytes: number) => string;
|
|
5
6
|
declare const createSourceEntry: (filename: string, dataname: string, content: Buffer, contentGzip: Buffer, mimeType: string, sha256: string, isGzip: boolean) => CppCodeSource;
|
|
6
|
-
declare const updateExtensionGroup: (extension: string) => void;
|
|
7
|
-
export
|
|
7
|
+
declare const updateExtensionGroup: (filesByExtension: ExtensionGroups, extension: string) => void;
|
|
8
|
+
export declare function main(): void;
|
|
9
|
+
export { calculateCompressionRatio, createSourceEntry, formatCompressionLog, formatSize, shouldUseGzip, updateExtensionGroup };
|
package/dist/index.js
CHANGED
|
@@ -3,8 +3,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.updateExtensionGroup = exports.shouldUseGzip = exports.formatCompressionLog = exports.createSourceEntry = exports.calculateCompressionRatio = void 0;
|
|
7
|
-
|
|
6
|
+
exports.updateExtensionGroup = exports.shouldUseGzip = exports.formatSize = exports.formatCompressionLog = exports.createSourceEntry = exports.calculateCompressionRatio = void 0;
|
|
7
|
+
exports.main = main;
|
|
8
8
|
const node_fs_1 = require("node:fs");
|
|
9
9
|
const node_path_1 = __importDefault(require("node:path"));
|
|
10
10
|
const node_zlib_1 = require("node:zlib");
|
|
@@ -16,13 +16,6 @@ const errorMessages_1 = require("./errorMessages");
|
|
|
16
16
|
const file_1 = require("./file");
|
|
17
17
|
const GZIP_MIN_SIZE = 1024;
|
|
18
18
|
const GZIP_MIN_REDUCTION_RATIO = 0.85;
|
|
19
|
-
const summary = {
|
|
20
|
-
filecount: 0,
|
|
21
|
-
size: 0,
|
|
22
|
-
gzipsize: 0
|
|
23
|
-
};
|
|
24
|
-
const sources = [];
|
|
25
|
-
const filesByExtension = [];
|
|
26
19
|
const shouldUseGzip = (originalSize, compressedSize) => originalSize > GZIP_MIN_SIZE && compressedSize < originalSize * GZIP_MIN_REDUCTION_RATIO;
|
|
27
20
|
exports.shouldUseGzip = shouldUseGzip;
|
|
28
21
|
const calculateCompressionRatio = (originalSize, compressedSize) => Math.round((compressedSize / originalSize) * 100);
|
|
@@ -36,6 +29,12 @@ const formatCompressionLog = (filename, padding, originalSize, compressedSize, u
|
|
|
36
29
|
return (0, consoleColor_1.yellowLog)(` [${filename}] ${padding} x gzip unused ${tooSmall}${sizeInfo}`);
|
|
37
30
|
};
|
|
38
31
|
exports.formatCompressionLog = formatCompressionLog;
|
|
32
|
+
const formatSize = (bytes) => {
|
|
33
|
+
if (bytes < 1024)
|
|
34
|
+
return `${bytes}B`;
|
|
35
|
+
return `${Math.round(bytes / 1024)}kB`;
|
|
36
|
+
};
|
|
37
|
+
exports.formatSize = formatSize;
|
|
39
38
|
const createSourceEntry = (filename, dataname, content, contentGzip, mimeType, sha256, isGzip) => ({
|
|
40
39
|
filename,
|
|
41
40
|
dataname,
|
|
@@ -47,7 +46,7 @@ const createSourceEntry = (filename, dataname, content, contentGzip, mimeType, s
|
|
|
47
46
|
sha256
|
|
48
47
|
});
|
|
49
48
|
exports.createSourceEntry = createSourceEntry;
|
|
50
|
-
const updateExtensionGroup = (extension) => {
|
|
49
|
+
const updateExtensionGroup = (filesByExtension, extension) => {
|
|
51
50
|
const group = filesByExtension.find((fe) => fe.extension === extension);
|
|
52
51
|
if (group)
|
|
53
52
|
group.count += 1;
|
|
@@ -55,47 +54,66 @@ const updateExtensionGroup = (extension) => {
|
|
|
55
54
|
filesByExtension.push({ extension, count: 1 });
|
|
56
55
|
};
|
|
57
56
|
exports.updateExtensionGroup = updateExtensionGroup;
|
|
58
|
-
|
|
59
|
-
const
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
57
|
+
function main() {
|
|
58
|
+
const summary = {
|
|
59
|
+
filecount: 0,
|
|
60
|
+
size: 0,
|
|
61
|
+
gzipsize: 0
|
|
62
|
+
};
|
|
63
|
+
const sources = [];
|
|
64
|
+
const filesByExtension = [];
|
|
65
|
+
console.log('Collecting source files');
|
|
66
|
+
const files = (0, file_1.getFiles)();
|
|
67
|
+
if (files.size === 0) {
|
|
68
|
+
console.error(`Directory ${commandLine_1.cmdLine.sourcepath} is empty`);
|
|
69
|
+
process.exit(1);
|
|
70
|
+
}
|
|
71
|
+
console.log();
|
|
72
|
+
console.log('Translation to header file');
|
|
73
|
+
const longestFilename = [...files.keys()].reduce((p, c) => Math.max(c.length, p), 0);
|
|
74
|
+
for (const [originalFilename, fileData] of files) {
|
|
75
|
+
const { content, hash: sha256 } = fileData;
|
|
76
|
+
const mimeType = (0, mime_types_1.lookup)(originalFilename) || 'text/plain';
|
|
77
|
+
if (!(0, mime_types_1.lookup)(originalFilename))
|
|
78
|
+
console.log((0, consoleColor_1.yellowLog)(` [${originalFilename}] unknown MIME type for extension '${node_path_1.default.extname(originalFilename)}', using text/plain`));
|
|
79
|
+
summary.filecount++;
|
|
80
|
+
const filename = originalFilename.replace(/\\/g, '/');
|
|
81
|
+
let dataname = filename.replace(/\W/g, '_');
|
|
82
|
+
if (/^\d/.test(dataname))
|
|
83
|
+
dataname = '_' + dataname;
|
|
84
|
+
let extension = node_path_1.default.extname(filename).toUpperCase();
|
|
85
|
+
if (extension.startsWith('.'))
|
|
86
|
+
extension = extension.slice(1);
|
|
87
|
+
updateExtensionGroup(filesByExtension, extension);
|
|
88
|
+
summary.size += content.length;
|
|
89
|
+
const zipContent = (0, node_zlib_1.gzipSync)(content, { level: 9 });
|
|
90
|
+
const useGzip = shouldUseGzip(content.length, zipContent.length);
|
|
91
|
+
summary.gzipsize += useGzip ? zipContent.length : content.length;
|
|
92
|
+
sources.push(createSourceEntry(filename, dataname, content, zipContent, mimeType, sha256, useGzip));
|
|
93
|
+
const padding = ' '.repeat(longestFilename - originalFilename.length);
|
|
94
|
+
console.log(formatCompressionLog(originalFilename, padding, content.length, zipContent.length, useGzip));
|
|
95
|
+
}
|
|
96
|
+
console.log('');
|
|
97
|
+
filesByExtension.sort((left, right) => left.extension.localeCompare(right.extension));
|
|
98
|
+
if (commandLine_1.cmdLine.maxSize !== undefined && summary.size > commandLine_1.cmdLine.maxSize) {
|
|
99
|
+
console.error((0, errorMessages_1.getSizeBudgetExceededError)('size', commandLine_1.cmdLine.maxSize, summary.size));
|
|
100
|
+
process.exit(1);
|
|
101
|
+
}
|
|
102
|
+
if (commandLine_1.cmdLine.maxGzipSize !== undefined && summary.gzipsize > commandLine_1.cmdLine.maxGzipSize) {
|
|
103
|
+
console.error((0, errorMessages_1.getSizeBudgetExceededError)('gzipSize', commandLine_1.cmdLine.maxGzipSize, summary.gzipsize));
|
|
104
|
+
process.exit(1);
|
|
105
|
+
}
|
|
106
|
+
if (commandLine_1.cmdLine.dryRun) {
|
|
107
|
+
console.log(`[DRY RUN] ${summary.filecount} files, ${formatSize(summary.size)} original size, ${formatSize(summary.gzipsize)} gzip size`);
|
|
108
|
+
console.log(`[DRY RUN] Would write to ${commandLine_1.cmdLine.outputfile}`);
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
const cppFile = (0, cppCode_1.getCppCode)(sources, filesByExtension);
|
|
112
|
+
(0, node_fs_1.mkdirSync)(node_path_1.default.normalize(node_path_1.default.dirname(commandLine_1.cmdLine.outputfile)), { recursive: true });
|
|
113
|
+
(0, node_fs_1.writeFileSync)(commandLine_1.cmdLine.outputfile, cppFile, { flush: true, encoding: 'utf8' });
|
|
114
|
+
console.log(`${summary.filecount} files, ${formatSize(summary.size)} original size, ${formatSize(summary.gzipsize)} gzip size`);
|
|
115
|
+
console.log(`${commandLine_1.cmdLine.outputfile} ${formatSize(cppFile.length)} size`);
|
|
116
|
+
if (commandLine_1.cmdLine.engine === 'psychic' || commandLine_1.cmdLine.engine === 'espidf')
|
|
117
|
+
console.log('\n' + (0, errorMessages_1.getMaxUriHandlersHint)(commandLine_1.cmdLine.engine, sources.length, commandLine_1.cmdLine.espmethod));
|
|
94
118
|
}
|
|
95
|
-
|
|
96
|
-
(0, node_fs_1.mkdirSync)(node_path_1.default.normalize(node_path_1.default.dirname(commandLine_1.cmdLine.outputfile)), { recursive: true });
|
|
97
|
-
(0, node_fs_1.writeFileSync)(commandLine_1.cmdLine.outputfile, cppFile, { flush: true, encoding: 'utf8' });
|
|
98
|
-
console.log(`${summary.filecount} files, ${Math.round(summary.size / 1024)}kB original size, ${Math.round(summary.gzipsize / 1024)}kB gzip size`);
|
|
99
|
-
console.log(`${commandLine_1.cmdLine.outputfile} ${Math.round(cppFile.length / 1024)}kB size`);
|
|
100
|
-
if (commandLine_1.cmdLine.engine === 'psychic' || commandLine_1.cmdLine.engine === 'psychic2' || commandLine_1.cmdLine.engine === 'espidf')
|
|
101
|
-
console.log('\n' + (0, errorMessages_1.getMaxUriHandlersHint)(commandLine_1.cmdLine.engine, sources.length));
|
|
119
|
+
main();
|