svelteesp32 1.14.0 → 1.16.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 +231 -485
- package/dist/commandLine.d.ts +8 -1
- package/dist/commandLine.js +103 -3
- package/dist/cppCode.js +209 -12
- package/dist/cppCodeEspIdf.d.ts +1 -1
- package/dist/cppCodeEspIdf.js +12 -4
- package/dist/errorMessages.d.ts +1 -0
- package/dist/errorMessages.js +28 -1
- package/dist/index.js +8 -0
- package/package.json +1 -1
package/dist/commandLine.d.ts
CHANGED
|
@@ -10,6 +10,9 @@ interface ICopyFilesArguments {
|
|
|
10
10
|
created: boolean;
|
|
11
11
|
version: string;
|
|
12
12
|
exclude: string[];
|
|
13
|
+
basePath: string;
|
|
14
|
+
maxSize?: number;
|
|
15
|
+
maxGzipSize?: number;
|
|
13
16
|
noIndexCheck?: boolean;
|
|
14
17
|
help?: boolean;
|
|
15
18
|
}
|
|
@@ -25,10 +28,14 @@ interface IRcFileConfig {
|
|
|
25
28
|
created?: boolean;
|
|
26
29
|
version?: string;
|
|
27
30
|
exclude?: string[];
|
|
31
|
+
basePath?: string;
|
|
32
|
+
maxSize?: number | string;
|
|
33
|
+
maxGzipSize?: number | string;
|
|
28
34
|
}
|
|
35
|
+
declare function parseSize(value: string, name: string): number;
|
|
29
36
|
declare function getNpmPackageVariable(packageJson: Record<string, unknown>, variableName: string): string | undefined;
|
|
30
37
|
declare function hasNpmVariables(config: IRcFileConfig): boolean;
|
|
31
38
|
declare function interpolateNpmVariables(config: IRcFileConfig, rcFilePath: string): IRcFileConfig;
|
|
32
|
-
export { getNpmPackageVariable, hasNpmVariables, interpolateNpmVariables };
|
|
39
|
+
export { getNpmPackageVariable, hasNpmVariables, interpolateNpmVariables, parseSize };
|
|
33
40
|
export declare function formatConfiguration(cmdLine: ICopyFilesArguments): string;
|
|
34
41
|
export declare const cmdLine: ICopyFilesArguments;
|
package/dist/commandLine.js
CHANGED
|
@@ -7,6 +7,7 @@ exports.cmdLine = void 0;
|
|
|
7
7
|
exports.getNpmPackageVariable = getNpmPackageVariable;
|
|
8
8
|
exports.hasNpmVariables = hasNpmVariables;
|
|
9
9
|
exports.interpolateNpmVariables = interpolateNpmVariables;
|
|
10
|
+
exports.parseSize = parseSize;
|
|
10
11
|
exports.formatConfiguration = formatConfiguration;
|
|
11
12
|
const node_fs_1 = require("node:fs");
|
|
12
13
|
const node_os_1 = require("node:os");
|
|
@@ -34,6 +35,9 @@ Options:
|
|
|
34
35
|
--cachetime <seconds> max-age cache time in seconds (default: 0)
|
|
35
36
|
--exclude <pattern> Exclude files matching glob pattern (repeatable or comma-separated)
|
|
36
37
|
Examples: --exclude="*.map" --exclude="test/**/*.ts"
|
|
38
|
+
--basepath <path> URL prefix for all routes (e.g., "/ui") (default: "")
|
|
39
|
+
--maxsize <size> Maximum total uncompressed size (e.g., 400k, 1.5m, 409600)
|
|
40
|
+
--maxgzipsize <size> Maximum total gzip size (e.g., 150k, 1m, 153600)
|
|
37
41
|
-h, --help Shows this help
|
|
38
42
|
|
|
39
43
|
RC File:
|
|
@@ -66,6 +70,36 @@ function validateTriState(value, name) {
|
|
|
66
70
|
return value;
|
|
67
71
|
throw new Error(`Invalid ${name}: ${value}`);
|
|
68
72
|
}
|
|
73
|
+
function validateBasePath(value) {
|
|
74
|
+
if (value === '')
|
|
75
|
+
return value;
|
|
76
|
+
if (!value.startsWith('/'))
|
|
77
|
+
throw new Error(`basePath must start with /: ${value}`);
|
|
78
|
+
if (value.endsWith('/'))
|
|
79
|
+
throw new Error(`basePath must not end with /: ${value}`);
|
|
80
|
+
if (value.includes('//'))
|
|
81
|
+
throw new Error(`basePath must not contain //: ${value}`);
|
|
82
|
+
return value;
|
|
83
|
+
}
|
|
84
|
+
function parseSize(value, name) {
|
|
85
|
+
const trimmed = value.trim();
|
|
86
|
+
const match = trimmed.match(/^(\d+(?:\.\d+)?)\s*([KMkm])?$/);
|
|
87
|
+
if (!match || !match[1])
|
|
88
|
+
throw new Error(`${name} must be a positive number with optional k/K (×1024) or m/M (×1024²) suffix: ${value}`);
|
|
89
|
+
const numericPart = Number.parseFloat(match[1]);
|
|
90
|
+
const suffix = match[2]?.toLowerCase();
|
|
91
|
+
let bytes;
|
|
92
|
+
if (suffix === 'k')
|
|
93
|
+
bytes = numericPart * 1024;
|
|
94
|
+
else if (suffix === 'm')
|
|
95
|
+
bytes = numericPart * 1024 * 1024;
|
|
96
|
+
else
|
|
97
|
+
bytes = numericPart;
|
|
98
|
+
bytes = Math.round(bytes);
|
|
99
|
+
if (bytes <= 0 || !Number.isFinite(bytes))
|
|
100
|
+
throw new Error(`${name} must be a positive integer: ${value}`);
|
|
101
|
+
return bytes;
|
|
102
|
+
}
|
|
69
103
|
const DEFAULT_EXCLUDE_PATTERNS = [
|
|
70
104
|
'.DS_Store',
|
|
71
105
|
'Thumbs.db',
|
|
@@ -136,6 +170,7 @@ function hasNpmVariables(config) {
|
|
|
136
170
|
checkStringForNpmVariable(config.espmethod) ||
|
|
137
171
|
checkStringForNpmVariable(config.define) ||
|
|
138
172
|
checkStringForNpmVariable(config.version) ||
|
|
173
|
+
checkStringForNpmVariable(config.basePath) ||
|
|
139
174
|
(Array.isArray(config.exclude) && config.exclude.some((pattern) => checkStringForNpmVariable(pattern))) ||
|
|
140
175
|
false);
|
|
141
176
|
}
|
|
@@ -155,6 +190,8 @@ function interpolateNpmVariables(config, rcFilePath) {
|
|
|
155
190
|
affectedFields.push('espmethod');
|
|
156
191
|
if (config.define?.includes('$npm_package_'))
|
|
157
192
|
affectedFields.push('define');
|
|
193
|
+
if (config.basePath?.includes('$npm_package_'))
|
|
194
|
+
affectedFields.push('basePath');
|
|
158
195
|
if (config.exclude)
|
|
159
196
|
for (const [index, pattern] of config.exclude.entries())
|
|
160
197
|
if (pattern.includes('$npm_package_'))
|
|
@@ -179,6 +216,8 @@ function interpolateNpmVariables(config, rcFilePath) {
|
|
|
179
216
|
result.define = interpolateString(result.define);
|
|
180
217
|
if (result.version)
|
|
181
218
|
result.version = interpolateString(result.version);
|
|
219
|
+
if (result.basePath)
|
|
220
|
+
result.basePath = interpolateString(result.basePath);
|
|
182
221
|
if (result.exclude)
|
|
183
222
|
result.exclude = result.exclude.map((pattern) => interpolateString(pattern));
|
|
184
223
|
return result;
|
|
@@ -211,7 +250,10 @@ function validateRcConfig(config, rcPath) {
|
|
|
211
250
|
'cachetime',
|
|
212
251
|
'created',
|
|
213
252
|
'version',
|
|
214
|
-
'exclude'
|
|
253
|
+
'exclude',
|
|
254
|
+
'basePath',
|
|
255
|
+
'maxSize',
|
|
256
|
+
'maxGzipSize'
|
|
215
257
|
]);
|
|
216
258
|
for (const key of Object.keys(configObject))
|
|
217
259
|
if (!validKeys.has(key))
|
|
@@ -232,6 +274,30 @@ function validateRcConfig(config, rcPath) {
|
|
|
232
274
|
if (typeof pattern !== 'string')
|
|
233
275
|
throw new TypeError('All exclude patterns must be strings');
|
|
234
276
|
}
|
|
277
|
+
if (configObject['maxSize'] !== undefined) {
|
|
278
|
+
const value = configObject['maxSize'];
|
|
279
|
+
if (typeof value === 'string')
|
|
280
|
+
try {
|
|
281
|
+
configObject['maxSize'] = parseSize(value, 'maxSize');
|
|
282
|
+
}
|
|
283
|
+
catch {
|
|
284
|
+
throw new TypeError(`Invalid maxSize in RC file: ${value} (must be a positive number with optional k/m suffix)`);
|
|
285
|
+
}
|
|
286
|
+
else if (typeof value !== 'number' || Number.isNaN(value) || value <= 0)
|
|
287
|
+
throw new TypeError(`Invalid maxSize in RC file: ${value} (must be a positive number)`);
|
|
288
|
+
}
|
|
289
|
+
if (configObject['maxGzipSize'] !== undefined) {
|
|
290
|
+
const value = configObject['maxGzipSize'];
|
|
291
|
+
if (typeof value === 'string')
|
|
292
|
+
try {
|
|
293
|
+
configObject['maxGzipSize'] = parseSize(value, 'maxGzipSize');
|
|
294
|
+
}
|
|
295
|
+
catch {
|
|
296
|
+
throw new TypeError(`Invalid maxGzipSize in RC file: ${value} (must be a positive number with optional k/m suffix)`);
|
|
297
|
+
}
|
|
298
|
+
else if (typeof value !== 'number' || Number.isNaN(value) || value <= 0)
|
|
299
|
+
throw new TypeError(`Invalid maxGzipSize in RC file: ${value} (must be a positive number)`);
|
|
300
|
+
}
|
|
235
301
|
return configObject;
|
|
236
302
|
}
|
|
237
303
|
function parseArguments() {
|
|
@@ -264,7 +330,8 @@ function parseArguments() {
|
|
|
264
330
|
espmethod: 'initSvelteStaticFiles',
|
|
265
331
|
define: 'SVELTEESP32',
|
|
266
332
|
cachetime: 0,
|
|
267
|
-
exclude: [...DEFAULT_EXCLUDE_PATTERNS]
|
|
333
|
+
exclude: [...DEFAULT_EXCLUDE_PATTERNS],
|
|
334
|
+
basePath: ''
|
|
268
335
|
};
|
|
269
336
|
if (rcConfig.engine)
|
|
270
337
|
result.engine = rcConfig.engine;
|
|
@@ -286,6 +353,12 @@ function parseArguments() {
|
|
|
286
353
|
result.espmethod = rcConfig.espmethod;
|
|
287
354
|
if (rcConfig.define)
|
|
288
355
|
result.define = rcConfig.define;
|
|
356
|
+
if (rcConfig.basePath !== undefined)
|
|
357
|
+
result.basePath = validateBasePath(rcConfig.basePath);
|
|
358
|
+
if (rcConfig.maxSize !== undefined)
|
|
359
|
+
result.maxSize = rcConfig.maxSize;
|
|
360
|
+
if (rcConfig.maxGzipSize !== undefined)
|
|
361
|
+
result.maxGzipSize = rcConfig.maxGzipSize;
|
|
289
362
|
if (rcConfig.exclude && rcConfig.exclude.length > 0)
|
|
290
363
|
result.exclude = [...rcConfig.exclude];
|
|
291
364
|
const cliExclude = [];
|
|
@@ -342,6 +415,15 @@ function parseArguments() {
|
|
|
342
415
|
cliExclude.push(...patterns);
|
|
343
416
|
break;
|
|
344
417
|
}
|
|
418
|
+
case 'basepath':
|
|
419
|
+
result.basePath = validateBasePath(value);
|
|
420
|
+
break;
|
|
421
|
+
case 'maxsize':
|
|
422
|
+
result.maxSize = parseSize(value, '--maxsize');
|
|
423
|
+
break;
|
|
424
|
+
case 'maxgzipsize':
|
|
425
|
+
result.maxGzipSize = parseSize(value, '--maxgzipsize');
|
|
426
|
+
break;
|
|
345
427
|
default:
|
|
346
428
|
throw new Error(`Unknown flag: ${flag}`);
|
|
347
429
|
}
|
|
@@ -351,7 +433,7 @@ function parseArguments() {
|
|
|
351
433
|
result.created = true;
|
|
352
434
|
continue;
|
|
353
435
|
}
|
|
354
|
-
if (argument === '--
|
|
436
|
+
if (argument === '--noindexcheck') {
|
|
355
437
|
result.noIndexCheck = true;
|
|
356
438
|
continue;
|
|
357
439
|
}
|
|
@@ -434,6 +516,18 @@ function parseArguments() {
|
|
|
434
516
|
index++;
|
|
435
517
|
break;
|
|
436
518
|
}
|
|
519
|
+
case 'basepath':
|
|
520
|
+
result.basePath = validateBasePath(nextArgument);
|
|
521
|
+
index++;
|
|
522
|
+
break;
|
|
523
|
+
case 'maxsize':
|
|
524
|
+
result.maxSize = parseSize(nextArgument, '--maxsize');
|
|
525
|
+
index++;
|
|
526
|
+
break;
|
|
527
|
+
case 'maxgzipsize':
|
|
528
|
+
result.maxGzipSize = parseSize(nextArgument, '--maxgzipsize');
|
|
529
|
+
index++;
|
|
530
|
+
break;
|
|
437
531
|
default:
|
|
438
532
|
throw new Error(`Unknown flag: --${flag}`);
|
|
439
533
|
}
|
|
@@ -466,6 +560,12 @@ function formatConfiguration(cmdLine) {
|
|
|
466
560
|
parts.push(`espmethod=${cmdLine.espmethod}`);
|
|
467
561
|
if (cmdLine.define)
|
|
468
562
|
parts.push(`define=${cmdLine.define}`);
|
|
563
|
+
if (cmdLine.basePath)
|
|
564
|
+
parts.push(`basePath=${cmdLine.basePath}`);
|
|
565
|
+
if (cmdLine.maxSize !== undefined)
|
|
566
|
+
parts.push(`maxSize=${cmdLine.maxSize}`);
|
|
567
|
+
if (cmdLine.maxGzipSize !== undefined)
|
|
568
|
+
parts.push(`maxGzipSize=${cmdLine.maxGzipSize}`);
|
|
469
569
|
if (cmdLine.exclude.length > 0)
|
|
470
570
|
parts.push(`exclude=[${cmdLine.exclude.join(', ')}]`);
|
|
471
571
|
return parts.join(' ');
|
package/dist/cppCode.js
CHANGED
|
@@ -108,11 +108,15 @@ struct {{definePrefix}}_FileInfo {
|
|
|
108
108
|
// File manifest array
|
|
109
109
|
const {{definePrefix}}_FileInfo {{definePrefix}}_FILES[] = {
|
|
110
110
|
{{#each sources}}
|
|
111
|
-
{ "/{{this.filename}}", {{this.length}}, {{this.gzipSizeForManifest}}, {{this.etagForManifest}}, "{{this.mime}}" },
|
|
111
|
+
{ "{{../basePath}}/{{this.filename}}", {{this.length}}, {{this.gzipSizeForManifest}}, {{this.etagForManifest}}, "{{this.mime}}" },
|
|
112
112
|
{{/each}}
|
|
113
113
|
};
|
|
114
114
|
const size_t {{definePrefix}}_FILE_COUNT = sizeof({{definePrefix}}_FILES) / sizeof({{definePrefix}}_FILES[0]);
|
|
115
115
|
`;
|
|
116
|
+
const hookSection = `
|
|
117
|
+
// File served hook - override with your own implementation
|
|
118
|
+
extern "C" void __attribute__((weak)) {{definePrefix}}_onFileServed(const char* path, int statusCode) {}
|
|
119
|
+
`;
|
|
116
120
|
const psychicTemplate = `
|
|
117
121
|
//engine: PsychicHttpServer
|
|
118
122
|
//config: {{{config}}}
|
|
@@ -137,19 +141,23 @@ ${etagArraysSection}
|
|
|
137
141
|
//
|
|
138
142
|
${manifestSection}
|
|
139
143
|
|
|
144
|
+
//
|
|
145
|
+
${hookSection}
|
|
146
|
+
|
|
140
147
|
//
|
|
141
148
|
// Http Handlers
|
|
142
149
|
void {{methodName}}(PsychicHttpServer * server) {
|
|
143
150
|
{{#each sources}}
|
|
144
151
|
//
|
|
145
152
|
// {{this.filename}}
|
|
146
|
-
{{#if this.isDefault}}server->defaultEndpoint = {{/if}}server->on("/{{this.filename}}", HTTP_GET, [](PsychicRequest * request) {
|
|
153
|
+
{{#if this.isDefault}}{{#unless ../basePath}}server->defaultEndpoint = {{/unless}}{{/if}}server->on("{{../basePath}}/{{this.filename}}", HTTP_GET, [](PsychicRequest * request) {
|
|
147
154
|
|
|
148
155
|
{{#switch ../etag}}
|
|
149
156
|
{{#case "true"}}
|
|
150
157
|
if (request->hasHeader("If-None-Match") && request->header("If-None-Match").equals(etag_{{this.dataname}})) {
|
|
151
158
|
PsychicResponse response304(request);
|
|
152
159
|
response304.setCode(304);
|
|
160
|
+
{{../definePrefix}}_onFileServed("{{../basePath}}/{{this.filename}}", 304);
|
|
153
161
|
return response304.send();
|
|
154
162
|
}
|
|
155
163
|
{{/case}}
|
|
@@ -158,6 +166,7 @@ void {{methodName}}(PsychicHttpServer * server) {
|
|
|
158
166
|
if (request->hasHeader("If-None-Match") && request->header("If-None-Match").equals(etag_{{this.dataname}})) {
|
|
159
167
|
PsychicResponse response304(request);
|
|
160
168
|
response304.setCode(304);
|
|
169
|
+
{{../definePrefix}}_onFileServed("{{../basePath}}/{{this.filename}}", 304);
|
|
161
170
|
return response304.send();
|
|
162
171
|
}
|
|
163
172
|
#endif
|
|
@@ -177,7 +186,7 @@ void {{methodName}}(PsychicHttpServer * server) {
|
|
|
177
186
|
{{#if this.isGzip}}
|
|
178
187
|
#ifdef {{../definePrefix}}_ENABLE_GZIP
|
|
179
188
|
response.addHeader("Content-Encoding", "gzip");
|
|
180
|
-
#endif
|
|
189
|
+
#endif
|
|
181
190
|
{{/if}}
|
|
182
191
|
{{/case}}
|
|
183
192
|
{{/switch}}
|
|
@@ -201,7 +210,93 @@ void {{methodName}}(PsychicHttpServer * server) {
|
|
|
201
210
|
response.addHeader("Cache-Control", "no-cache");
|
|
202
211
|
{{/../cacheTime}}
|
|
203
212
|
response.addHeader("ETag", etag_{{this.dataname}});
|
|
204
|
-
#endif
|
|
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
|
|
205
300
|
{{/case}}
|
|
206
301
|
{{/switch}}
|
|
207
302
|
|
|
@@ -217,12 +312,14 @@ void {{methodName}}(PsychicHttpServer * server) {
|
|
|
217
312
|
response.setContent(datagzip_{{this.dataname}}, {{this.lengthGzip}});
|
|
218
313
|
#else
|
|
219
314
|
response.setContent(data_{{this.dataname}}, {{this.length}});
|
|
220
|
-
#endif
|
|
315
|
+
#endif
|
|
221
316
|
{{/case}}
|
|
222
317
|
{{/switch}}
|
|
223
318
|
|
|
319
|
+
{{../definePrefix}}_onFileServed("{{../basePath}}", 200);
|
|
224
320
|
return response.send();
|
|
225
321
|
});
|
|
322
|
+
{{/if}}{{/if}}
|
|
226
323
|
|
|
227
324
|
{{/each}}
|
|
228
325
|
}`;
|
|
@@ -249,18 +346,22 @@ ${etagArraysSection}
|
|
|
249
346
|
//
|
|
250
347
|
${manifestSection}
|
|
251
348
|
|
|
349
|
+
//
|
|
350
|
+
${hookSection}
|
|
351
|
+
|
|
252
352
|
//
|
|
253
353
|
// Http Handlers
|
|
254
354
|
void {{methodName}}(PsychicHttpServer * server) {
|
|
255
355
|
{{#each sources}}
|
|
256
356
|
//
|
|
257
357
|
// {{this.filename}}
|
|
258
|
-
{{#if this.isDefault}}server->defaultEndpoint = {{/if}}server->on("/{{this.filename}}", HTTP_GET, [](PsychicRequest * request, PsychicResponse * response) {
|
|
358
|
+
{{#if this.isDefault}}{{#unless ../basePath}}server->defaultEndpoint = {{/unless}}{{/if}}server->on("{{../basePath}}/{{this.filename}}", HTTP_GET, [](PsychicRequest * request, PsychicResponse * response) {
|
|
259
359
|
|
|
260
360
|
{{#switch ../etag}}
|
|
261
361
|
{{#case "true"}}
|
|
262
362
|
if (request->hasHeader("If-None-Match") && request->header("If-None-Match").equals(etag_{{this.dataname}})) {
|
|
263
363
|
response->setCode(304);
|
|
364
|
+
{{../definePrefix}}_onFileServed("{{../basePath}}/{{this.filename}}", 304);
|
|
264
365
|
return response->send();
|
|
265
366
|
}
|
|
266
367
|
{{/case}}
|
|
@@ -268,6 +369,7 @@ void {{methodName}}(PsychicHttpServer * server) {
|
|
|
268
369
|
#ifdef {{../definePrefix}}_ENABLE_ETAG
|
|
269
370
|
if (request->hasHeader("If-None-Match") && request->header("If-None-Match").equals(etag_{{this.dataname}})) {
|
|
270
371
|
response->setCode(304);
|
|
372
|
+
{{../definePrefix}}_onFileServed("{{../basePath}}/{{this.filename}}", 304);
|
|
271
373
|
return response->send();
|
|
272
374
|
}
|
|
273
375
|
#endif
|
|
@@ -286,7 +388,7 @@ void {{methodName}}(PsychicHttpServer * server) {
|
|
|
286
388
|
{{#if this.isGzip}}
|
|
287
389
|
#ifdef {{../definePrefix}}_ENABLE_GZIP
|
|
288
390
|
response->addHeader("Content-Encoding", "gzip");
|
|
289
|
-
#endif
|
|
391
|
+
#endif
|
|
290
392
|
{{/if}}
|
|
291
393
|
{{/case}}
|
|
292
394
|
{{/switch}}
|
|
@@ -310,7 +412,7 @@ void {{methodName}}(PsychicHttpServer * server) {
|
|
|
310
412
|
response->addHeader("Cache-Control", "no-cache");
|
|
311
413
|
{{/../cacheTime}}
|
|
312
414
|
response->addHeader("ETag", etag_{{this.dataname}});
|
|
313
|
-
#endif
|
|
415
|
+
#endif
|
|
314
416
|
{{/case}}
|
|
315
417
|
{{/switch}}
|
|
316
418
|
|
|
@@ -326,12 +428,97 @@ void {{methodName}}(PsychicHttpServer * server) {
|
|
|
326
428
|
response->setContent(datagzip_{{this.dataname}}, {{this.lengthGzip}});
|
|
327
429
|
#else
|
|
328
430
|
response->setContent(data_{{this.dataname}}, {{this.length}});
|
|
329
|
-
#endif
|
|
431
|
+
#endif
|
|
330
432
|
{{/case}}
|
|
331
433
|
{{/switch}}
|
|
332
434
|
|
|
435
|
+
{{../definePrefix}}_onFileServed("{{../basePath}}/{{this.filename}}", 200);
|
|
333
436
|
return response->send();
|
|
334
437
|
});
|
|
438
|
+
{{#if this.isDefault}}{{#if ../basePath}}
|
|
439
|
+
//
|
|
440
|
+
// {{this.filename}} (base path route)
|
|
441
|
+
server->on("{{../basePath}}", HTTP_GET, [](PsychicRequest * request, PsychicResponse * response) {
|
|
442
|
+
|
|
443
|
+
{{#switch ../etag}}
|
|
444
|
+
{{#case "true"}}
|
|
445
|
+
if (request->hasHeader("If-None-Match") && request->header("If-None-Match").equals(etag_{{this.dataname}})) {
|
|
446
|
+
response->setCode(304);
|
|
447
|
+
{{../definePrefix}}_onFileServed("{{../basePath}}", 304);
|
|
448
|
+
return response->send();
|
|
449
|
+
}
|
|
450
|
+
{{/case}}
|
|
451
|
+
{{#case "compiler"}}
|
|
452
|
+
#ifdef {{../definePrefix}}_ENABLE_ETAG
|
|
453
|
+
if (request->hasHeader("If-None-Match") && request->header("If-None-Match").equals(etag_{{this.dataname}})) {
|
|
454
|
+
response->setCode(304);
|
|
455
|
+
{{../definePrefix}}_onFileServed("{{../basePath}}", 304);
|
|
456
|
+
return response->send();
|
|
457
|
+
}
|
|
458
|
+
#endif
|
|
459
|
+
{{/case}}
|
|
460
|
+
{{/switch}}
|
|
461
|
+
|
|
462
|
+
response->setContentType("{{this.mime}}");
|
|
463
|
+
|
|
464
|
+
{{#switch ../gzip}}
|
|
465
|
+
{{#case "true"}}
|
|
466
|
+
{{#if this.isGzip}}
|
|
467
|
+
response->addHeader("Content-Encoding", "gzip");
|
|
468
|
+
{{/if}}
|
|
469
|
+
{{/case}}
|
|
470
|
+
{{#case "compiler"}}
|
|
471
|
+
{{#if this.isGzip}}
|
|
472
|
+
#ifdef {{../definePrefix}}_ENABLE_GZIP
|
|
473
|
+
response->addHeader("Content-Encoding", "gzip");
|
|
474
|
+
#endif
|
|
475
|
+
{{/if}}
|
|
476
|
+
{{/case}}
|
|
477
|
+
{{/switch}}
|
|
478
|
+
|
|
479
|
+
{{#switch ../etag}}
|
|
480
|
+
{{#case "true"}}
|
|
481
|
+
{{#../cacheTime}}
|
|
482
|
+
response->addHeader("Cache-Control", "max-age={{value}}");
|
|
483
|
+
{{/../cacheTime}}
|
|
484
|
+
{{^../cacheTime}}
|
|
485
|
+
response->addHeader("Cache-Control", "no-cache");
|
|
486
|
+
{{/../cacheTime}}
|
|
487
|
+
response->addHeader("ETag", etag_{{this.dataname}});
|
|
488
|
+
{{/case}}
|
|
489
|
+
{{#case "compiler"}}
|
|
490
|
+
#ifdef {{../definePrefix}}_ENABLE_ETAG
|
|
491
|
+
{{#../cacheTime}}
|
|
492
|
+
response->addHeader("Cache-Control", "max-age={{value}}");
|
|
493
|
+
{{/../cacheTime}}
|
|
494
|
+
{{^../cacheTime}}
|
|
495
|
+
response->addHeader("Cache-Control", "no-cache");
|
|
496
|
+
{{/../cacheTime}}
|
|
497
|
+
response->addHeader("ETag", etag_{{this.dataname}});
|
|
498
|
+
#endif
|
|
499
|
+
{{/case}}
|
|
500
|
+
{{/switch}}
|
|
501
|
+
|
|
502
|
+
{{#switch ../gzip}}
|
|
503
|
+
{{#case "true"}}
|
|
504
|
+
response->setContent(datagzip_{{this.dataname}}, {{this.lengthGzip}});
|
|
505
|
+
{{/case}}
|
|
506
|
+
{{#case "false"}}
|
|
507
|
+
response->setContent(data_{{this.dataname}}, {{this.length}});
|
|
508
|
+
{{/case}}
|
|
509
|
+
{{#case "compiler"}}
|
|
510
|
+
#ifdef {{../definePrefix}}_ENABLE_GZIP
|
|
511
|
+
response->setContent(datagzip_{{this.dataname}}, {{this.lengthGzip}});
|
|
512
|
+
#else
|
|
513
|
+
response->setContent(data_{{this.dataname}}, {{this.length}});
|
|
514
|
+
#endif
|
|
515
|
+
{{/case}}
|
|
516
|
+
{{/switch}}
|
|
517
|
+
|
|
518
|
+
{{../definePrefix}}_onFileServed("{{../basePath}}", 200);
|
|
519
|
+
return response->send();
|
|
520
|
+
});
|
|
521
|
+
{{/if}}{{/if}}
|
|
335
522
|
|
|
336
523
|
{{/each}}
|
|
337
524
|
}`;
|
|
@@ -357,18 +544,22 @@ ${etagArraysSection}
|
|
|
357
544
|
//
|
|
358
545
|
${manifestSection}
|
|
359
546
|
|
|
547
|
+
//
|
|
548
|
+
${hookSection}
|
|
549
|
+
|
|
360
550
|
//
|
|
361
551
|
// Http Handlers
|
|
362
552
|
void {{methodName}}(AsyncWebServer * server) {
|
|
363
553
|
{{#each sources}}
|
|
364
554
|
//
|
|
365
555
|
// {{this.filename}}
|
|
366
|
-
server->on("/{{this.filename}}", HTTP_GET, [](AsyncWebServerRequest * request) {
|
|
556
|
+
server->on("{{../basePath}}/{{this.filename}}", HTTP_GET, [](AsyncWebServerRequest * request) {
|
|
367
557
|
|
|
368
558
|
{{#switch ../etag}}
|
|
369
559
|
{{#case "true"}}
|
|
370
560
|
const AsyncWebHeader* h = request->getHeader("If-None-Match");
|
|
371
561
|
if (h && h->value().equals(etag_{{this.dataname}})) {
|
|
562
|
+
{{../definePrefix}}_onFileServed("{{../basePath}}/{{this.filename}}", 304);
|
|
372
563
|
request->send(304);
|
|
373
564
|
return;
|
|
374
565
|
}
|
|
@@ -377,6 +568,7 @@ void {{methodName}}(AsyncWebServer * server) {
|
|
|
377
568
|
#ifdef {{../definePrefix}}_ENABLE_ETAG
|
|
378
569
|
const AsyncWebHeader* h = request->getHeader("If-None-Match");
|
|
379
570
|
if (h && h->value().equals(etag_{{this.dataname}})) {
|
|
571
|
+
{{../definePrefix}}_onFileServed("{{../basePath}}/{{this.filename}}", 304);
|
|
380
572
|
request->send(304);
|
|
381
573
|
return;
|
|
382
574
|
}
|
|
@@ -429,15 +621,17 @@ void {{methodName}}(AsyncWebServer * server) {
|
|
|
429
621
|
{{/case}}
|
|
430
622
|
{{/switch}}
|
|
431
623
|
|
|
624
|
+
{{../definePrefix}}_onFileServed("{{../basePath}}/{{this.filename}}", 200);
|
|
432
625
|
request->send(response);
|
|
433
626
|
});
|
|
434
627
|
{{#if this.isDefault}}
|
|
435
|
-
server->on("/", HTTP_GET, [](AsyncWebServerRequest * request) {
|
|
628
|
+
server->on("{{#if ../basePath}}{{../basePath}}{{else}}/{{/if}}", HTTP_GET, [](AsyncWebServerRequest * request) {
|
|
436
629
|
|
|
437
630
|
{{#switch ../etag}}
|
|
438
631
|
{{#case "true"}}
|
|
439
632
|
const AsyncWebHeader* h = request->getHeader("If-None-Match");
|
|
440
633
|
if (h && h->value().equals(etag_{{this.dataname}})) {
|
|
634
|
+
{{../definePrefix}}_onFileServed("{{#if ../basePath}}{{../basePath}}{{else}}/{{/if}}", 304);
|
|
441
635
|
request->send(304);
|
|
442
636
|
return;
|
|
443
637
|
}
|
|
@@ -446,6 +640,7 @@ void {{methodName}}(AsyncWebServer * server) {
|
|
|
446
640
|
#ifdef {{../definePrefix}}_ENABLE_ETAG
|
|
447
641
|
const AsyncWebHeader* h = request->getHeader("If-None-Match");
|
|
448
642
|
if (h && h->value().equals(etag_{{this.dataname}})) {
|
|
643
|
+
{{../definePrefix}}_onFileServed("{{#if ../basePath}}{{../basePath}}{{else}}/{{/if}}", 304);
|
|
449
644
|
request->send(304);
|
|
450
645
|
return;
|
|
451
646
|
}
|
|
@@ -498,6 +693,7 @@ void {{methodName}}(AsyncWebServer * server) {
|
|
|
498
693
|
{{/case}}
|
|
499
694
|
{{/switch}}
|
|
500
695
|
|
|
696
|
+
{{../definePrefix}}_onFileServed("{{#if ../basePath}}{{../basePath}}{{else}}/{{/if}}", 200);
|
|
501
697
|
request->send(response);
|
|
502
698
|
});
|
|
503
699
|
{{/if}}
|
|
@@ -568,7 +764,8 @@ const getCppCode = (sources, filesByExtension) => {
|
|
|
568
764
|
version: commandLine_1.cmdLine.version,
|
|
569
765
|
methodName: commandLine_1.cmdLine.espmethod,
|
|
570
766
|
cacheTime: commandLine_1.cmdLine.cachetime ? { value: commandLine_1.cmdLine.cachetime } : undefined,
|
|
571
|
-
definePrefix: commandLine_1.cmdLine.define
|
|
767
|
+
definePrefix: commandLine_1.cmdLine.define,
|
|
768
|
+
basePath: commandLine_1.cmdLine.basePath
|
|
572
769
|
};
|
|
573
770
|
const rawCode = template(templateData, { helpers: createHandlebarsHelpers() });
|
|
574
771
|
return postProcessCppCode(rawCode);
|
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 { \"/{{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{{#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 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 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 httpd_resp_send(req, datagzip_{{this.dataname}}, {{this.lengthGzip}});\n{{/case}}\n{{#case \"false\"}}\n httpd_resp_send(req, data_{{this.dataname}}, {{this.length}});\n{{/case}}\n{{#case \"compiler\"}}\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
|
|
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}";
|