svelteesp32 3.1.2 → 3.1.3
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 +4 -3
- package/dist/commandLine.d.ts +1 -1
- package/dist/commandLine.js +43 -42
- package/dist/cppCode.d.ts +3 -1
- package/dist/cppCode.js +20 -6
- package/dist/cppCodeEspIdf.js +1 -1
- package/dist/errorMessages.d.ts +0 -1
- package/dist/errorMessages.js +0 -32
- package/dist/file.js +1 -1
- package/dist/index.js +7 -7
- package/dist/pipeline.d.ts +2 -2
- package/dist/pipeline.js +14 -16
- package/package.json +10 -10
package/README.md
CHANGED
|
@@ -88,7 +88,7 @@ void setup() {
|
|
|
88
88
|
|
|
89
89
|
## What's New
|
|
90
90
|
|
|
91
|
-
- **v3.1.0** — Removed `handlebars`, `picomatch`, and `mime-types` dependencies; C++ generation is now pure TypeScript with a built-in MIME type map and direct `tinyglobby` exclude handling. `--cachetime-html` → `--cachetimehtml`, `--cachetime-assets` → `--cachetimeassets` (CLI now matches RC file keys); `--dry-run` alias removed — use `--dryrun`
|
|
91
|
+
- **v3.1.0** — Removed `handlebars`, `picomatch`, and `mime-types` dependencies; C++ generation is now pure TypeScript with a built-in MIME type map and direct `tinyglobby` exclude handling. `--cachetime-html` → `--cachetimehtml`, `--cachetime-assets` → `--cachetimeassets` (CLI now matches RC file keys); `--dry-run` alias removed — use `--dryrun`. `SVELTEESP32_URI_HANDLERS`/`SVELTEESP32_MAX_URI_HANDLERS` (psychic/espidf) now reflect the exact registered route count, including the default `/` route and `--spa` catch-all
|
|
92
92
|
- **v3.0.0** — **Vite plugin** (`import { svelteESP32 } from 'svelteesp32/vite'`) generates the header automatically after every build — call with no argument for RC file mode or pass an options object for plugin-options mode; `npx svelteesp32 init` interactive RC file wizard; Node.js >= 22 required
|
|
93
93
|
- **v2.4.0** — `--analyze` for CI size budget checks (per-file table, exits 1 on over-budget); `--manifest` to write a companion JSON manifest alongside the header
|
|
94
94
|
- **v2.3.0** — `--cachetimehtml` and `--cachetimeassets` for per-type cache control (e.g. `no-cache` for HTML, 1-year for content-hashed JS/CSS)
|
|
@@ -379,7 +379,7 @@ void initSvelteStaticFiles(PsychicHttpServer * server) {
|
|
|
379
379
|
|
|
380
380
|
**Recommendation:** For ESP32-only projects, use PsychicHttpServer V2 (`-e psychic`) for the fastest, most stable experience.
|
|
381
381
|
|
|
382
|
-
**Note:** For PsychicHttp, configure `server.config.max_uri_handlers`. The generated header provides `SVELTEESP32_MAX_URI_HANDLERS` (
|
|
382
|
+
**Note:** For PsychicHttp and native ESP-IDF, configure `server.config.max_uri_handlers` / `httpd_config_t.max_uri_handlers`. The generated header provides `SVELTEESP32_URI_HANDLERS` (the exact number of routes registered, accounting for the default `/` route and the `--spa` catch-all handler) and `SVELTEESP32_MAX_URI_HANDLERS` (`SVELTEESP32_URI_HANDLERS` + 5 safety margin for your own custom routes) for use directly in your sketch.
|
|
383
383
|
|
|
384
384
|
---
|
|
385
385
|
|
|
@@ -576,7 +576,7 @@ Catch configuration issues at compile time with generated defines:
|
|
|
576
576
|
#endif
|
|
577
577
|
```
|
|
578
578
|
|
|
579
|
-
**Available defines:** `SVELTEESP32_COUNT`, `SVELTEESP32_SIZE`, `SVELTEESP32_SIZE_GZIP`, `SVELTEESP32_FILE_*`, `SVELTEESP32_*_FILES`
|
|
579
|
+
**Available defines:** `SVELTEESP32_COUNT`, `SVELTEESP32_SIZE`, `SVELTEESP32_SIZE_GZIP`, `SVELTEESP32_FILE_*`, `SVELTEESP32_*_FILES`, and (psychic/espidf only) `SVELTEESP32_URI_HANDLERS`, `SVELTEESP32_MAX_URI_HANDLERS`
|
|
580
580
|
|
|
581
581
|
### Runtime File Manifest
|
|
582
582
|
|
|
@@ -812,6 +812,7 @@ add_dependencies(${COMPONENT_LIB} frontend_header)
|
|
|
812
812
|
void app_main(void) {
|
|
813
813
|
// ... WiFi init ...
|
|
814
814
|
httpd_config_t config = HTTPD_DEFAULT_CONFIG();
|
|
815
|
+
config.max_uri_handlers = SVELTEESP32_MAX_URI_HANDLERS; // already defined in the header, includes a safety margin
|
|
815
816
|
httpd_handle_t server = NULL;
|
|
816
817
|
httpd_start(&server, &config);
|
|
817
818
|
initSvelteStaticFiles(server);
|
package/dist/commandLine.d.ts
CHANGED
|
@@ -55,4 +55,4 @@ declare function interpolateNpmVariables(config: IRcFileConfig, rcFilePath: stri
|
|
|
55
55
|
export declare function loadRcFileConfig(configPath?: string): Partial<IRcFileConfig>;
|
|
56
56
|
export declare function parseArguments(): ICopyFilesArguments;
|
|
57
57
|
export { getNpmPackageVariable, hasNpmVariables, interpolateNpmVariables, parseSize, validateCppIdentifier };
|
|
58
|
-
export declare function
|
|
58
|
+
export declare function formatConfig(commandLine: ICopyFilesArguments): string;
|
package/dist/commandLine.js
CHANGED
|
@@ -11,7 +11,7 @@ exports.hasNpmVariables = hasNpmVariables;
|
|
|
11
11
|
exports.interpolateNpmVariables = interpolateNpmVariables;
|
|
12
12
|
exports.parseSize = parseSize;
|
|
13
13
|
exports.validateCppIdentifier = validateCppIdentifier;
|
|
14
|
-
exports.
|
|
14
|
+
exports.formatConfig = formatConfig;
|
|
15
15
|
const node_fs_1 = require("node:fs");
|
|
16
16
|
const node_os_1 = require("node:os");
|
|
17
17
|
const node_path_1 = __importDefault(require("node:path"));
|
|
@@ -184,17 +184,17 @@ function getNpmPackageVariable(packageJson, variableName) {
|
|
|
184
184
|
return undefined;
|
|
185
185
|
return String(current);
|
|
186
186
|
}
|
|
187
|
-
function
|
|
187
|
+
function hasNpmVariable(value) {
|
|
188
188
|
return value?.includes('$npm_package_') ?? false;
|
|
189
189
|
}
|
|
190
190
|
function hasNpmVariables(config) {
|
|
191
|
-
return (
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
(Array.isArray(config.exclude) && config.exclude.some((pattern) =>
|
|
191
|
+
return (hasNpmVariable(config.sourcepath) ||
|
|
192
|
+
hasNpmVariable(config.outputfile) ||
|
|
193
|
+
hasNpmVariable(config.espmethod) ||
|
|
194
|
+
hasNpmVariable(config.define) ||
|
|
195
|
+
hasNpmVariable(config.version) ||
|
|
196
|
+
hasNpmVariable(config.basepath) ||
|
|
197
|
+
(Array.isArray(config.exclude) && config.exclude.some((pattern) => hasNpmVariable(pattern))));
|
|
198
198
|
}
|
|
199
199
|
function interpolateNpmVariables(config, rcFilePath) {
|
|
200
200
|
if (!hasNpmVariables(config))
|
|
@@ -338,7 +338,8 @@ function validateRcConfig(config, rcPath) {
|
|
|
338
338
|
if (configObject['exclude'] !== undefined) {
|
|
339
339
|
if (!Array.isArray(configObject['exclude']))
|
|
340
340
|
throw new TypeError("'exclude' in RC file must be an array");
|
|
341
|
-
|
|
341
|
+
const excludePatterns = configObject['exclude'];
|
|
342
|
+
for (const pattern of excludePatterns)
|
|
342
343
|
if (typeof pattern !== 'string')
|
|
343
344
|
throw new TypeError('All exclude patterns must be strings');
|
|
344
345
|
}
|
|
@@ -615,40 +616,40 @@ function parseArguments() {
|
|
|
615
616
|
throw new Error('--analyze and --dryrun are mutually exclusive. Use --analyze for CI budget checks or --dryrun for a developer route preview.');
|
|
616
617
|
return result;
|
|
617
618
|
}
|
|
618
|
-
function
|
|
619
|
-
const relativeOutput = node_path_1.default.relative(process.cwd(),
|
|
619
|
+
function formatConfig(commandLine) {
|
|
620
|
+
const relativeOutput = node_path_1.default.relative(process.cwd(), commandLine.outputfile);
|
|
620
621
|
const parts = [
|
|
621
|
-
`source=${
|
|
622
|
-
`engine=${
|
|
623
|
-
`sourcepath=${
|
|
622
|
+
`source=${commandLine.configSource}`,
|
|
623
|
+
`engine=${commandLine.engine}`,
|
|
624
|
+
`sourcepath=${commandLine.sourcepath}`,
|
|
624
625
|
`outputfile=${relativeOutput}`,
|
|
625
|
-
`etag=${
|
|
626
|
-
`gzip=${
|
|
627
|
-
`cachetime=${
|
|
626
|
+
`etag=${commandLine.etag}`,
|
|
627
|
+
`gzip=${commandLine.gzip}`,
|
|
628
|
+
`cachetime=${commandLine.cachetime}`
|
|
628
629
|
];
|
|
629
|
-
if (
|
|
630
|
-
parts.push(`cachetimeHtml=${
|
|
631
|
-
if (
|
|
632
|
-
parts.push(`cachetimeAssets=${
|
|
633
|
-
if (
|
|
634
|
-
parts.push(`created=${
|
|
635
|
-
if (
|
|
636
|
-
parts.push(`version=${
|
|
637
|
-
if (
|
|
638
|
-
parts.push(`espmethod=${
|
|
639
|
-
if (
|
|
640
|
-
parts.push(`define=${
|
|
641
|
-
if (
|
|
642
|
-
parts.push(`basePath=${
|
|
643
|
-
if (
|
|
644
|
-
parts.push(`maxSize=${
|
|
645
|
-
if (
|
|
646
|
-
parts.push(`maxGzipSize=${
|
|
647
|
-
if (
|
|
648
|
-
parts.push(`spa=${
|
|
649
|
-
if (
|
|
650
|
-
parts.push(`analyze=${
|
|
651
|
-
if (
|
|
652
|
-
parts.push(`exclude=[${
|
|
630
|
+
if (commandLine.cachetimeHtml !== undefined)
|
|
631
|
+
parts.push(`cachetimeHtml=${commandLine.cachetimeHtml}`);
|
|
632
|
+
if (commandLine.cachetimeAssets !== undefined)
|
|
633
|
+
parts.push(`cachetimeAssets=${commandLine.cachetimeAssets}`);
|
|
634
|
+
if (commandLine.created)
|
|
635
|
+
parts.push(`created=${commandLine.created}`);
|
|
636
|
+
if (commandLine.version)
|
|
637
|
+
parts.push(`version=${commandLine.version}`);
|
|
638
|
+
if (commandLine.espmethod)
|
|
639
|
+
parts.push(`espmethod=${commandLine.espmethod}`);
|
|
640
|
+
if (commandLine.define)
|
|
641
|
+
parts.push(`define=${commandLine.define}`);
|
|
642
|
+
if (commandLine.basePath)
|
|
643
|
+
parts.push(`basePath=${commandLine.basePath}`);
|
|
644
|
+
if (commandLine.maxSize !== undefined)
|
|
645
|
+
parts.push(`maxSize=${commandLine.maxSize}`);
|
|
646
|
+
if (commandLine.maxGzipSize !== undefined)
|
|
647
|
+
parts.push(`maxGzipSize=${commandLine.maxGzipSize}`);
|
|
648
|
+
if (commandLine.spa)
|
|
649
|
+
parts.push(`spa=${commandLine.spa}`);
|
|
650
|
+
if (commandLine.analyze)
|
|
651
|
+
parts.push(`analyze=${commandLine.analyze}`);
|
|
652
|
+
if (commandLine.exclude.length > 0)
|
|
653
|
+
parts.push(`exclude=[${commandLine.exclude.join(', ')}]`);
|
|
653
654
|
return parts.join(' ').replace(/[\n\r]/g, ' ');
|
|
654
655
|
}
|
package/dist/cppCode.d.ts
CHANGED
|
@@ -55,11 +55,13 @@ export type TemplateData = {
|
|
|
55
55
|
spa: boolean;
|
|
56
56
|
spaSource: TransformedSource | undefined;
|
|
57
57
|
isPsychic: boolean;
|
|
58
|
+
uriHandlers: string;
|
|
58
59
|
maxUriHandlers: string;
|
|
59
60
|
};
|
|
60
61
|
export declare const cacheCtrl: (source: TransformedSource) => string;
|
|
62
|
+
export declare const computeRouteCount: (sources: CppCodeSources, engine: ICopyFilesArguments["engine"], basePath: string, isSpa: boolean) => number;
|
|
61
63
|
export declare const genCommonHeader: (d: TemplateData) => string;
|
|
62
|
-
export declare const genDataArrays: (d: TemplateData,
|
|
64
|
+
export declare const genDataArrays: (d: TemplateData, isProgmem: boolean) => string;
|
|
63
65
|
export declare const genEtagArrays: (d: TemplateData) => string;
|
|
64
66
|
export declare const genManifest: (d: TemplateData) => string;
|
|
65
67
|
export declare const genHook: (d: TemplateData) => string;
|
package/dist/cppCode.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getCppCode = exports.genHook = exports.genManifest = exports.genEtagArrays = exports.genDataArrays = exports.genCommonHeader = exports.cacheCtrl = exports.sw = void 0;
|
|
3
|
+
exports.getCppCode = exports.genHook = exports.genManifest = exports.genEtagArrays = exports.genDataArrays = exports.genCommonHeader = exports.computeRouteCount = exports.cacheCtrl = exports.sw = void 0;
|
|
4
4
|
const commandLine_1 = require("./commandLine");
|
|
5
5
|
const cppCodeAsync_1 = require("./cppCodeAsync");
|
|
6
6
|
const cppCodeEspIdf_1 = require("./cppCodeEspIdf");
|
|
@@ -29,6 +29,18 @@ const transformSourceToTemplateData = (s, etag, effectiveCacheTime) => ({
|
|
|
29
29
|
});
|
|
30
30
|
const cacheCtrl = (source) => source.cacheTime ? `max-age=${source.cacheTime.value}` : 'no-cache';
|
|
31
31
|
exports.cacheCtrl = cacheCtrl;
|
|
32
|
+
const computeRouteCount = (sources, engine, basePath, isSpa) => {
|
|
33
|
+
const numberDefault = sources.filter((s) => s.filename === 'index.html' || s.filename === 'index.htm').length;
|
|
34
|
+
const hasDefault = numberDefault > 0;
|
|
35
|
+
if (engine === 'psychic') {
|
|
36
|
+
const defaultExtra = basePath ? numberDefault : 0;
|
|
37
|
+
const spaExtra = isSpa && hasDefault && basePath ? 1 : 0;
|
|
38
|
+
return sources.length + defaultExtra + spaExtra;
|
|
39
|
+
}
|
|
40
|
+
const spaExtra = isSpa && hasDefault ? 1 : 0;
|
|
41
|
+
return sources.length + numberDefault + spaExtra;
|
|
42
|
+
};
|
|
43
|
+
exports.computeRouteCount = computeRouteCount;
|
|
32
44
|
const genCommonHeader = (d) => {
|
|
33
45
|
const lines = [];
|
|
34
46
|
const etagWarn = (0, exports.sw)(d.etag, {
|
|
@@ -64,7 +76,7 @@ const genCommonHeader = (d) => {
|
|
|
64
76
|
lines.push(`#define ${d.definePrefix}_VERSION "${d.version}"`);
|
|
65
77
|
lines.push(`#define ${d.definePrefix}_COUNT ${d.fileCount}`, `#define ${d.definePrefix}_SIZE ${d.fileSize}`, `#define ${d.definePrefix}_SIZE_GZIP ${d.fileGzipSize}`);
|
|
66
78
|
if (d.isPsychic)
|
|
67
|
-
lines.push(`#define ${d.definePrefix}_MAX_URI_HANDLERS ${d.maxUriHandlers}`);
|
|
79
|
+
lines.push(`#define ${d.definePrefix}_URI_HANDLERS ${d.uriHandlers}`, `#define ${d.definePrefix}_MAX_URI_HANDLERS ${d.maxUriHandlers}`);
|
|
68
80
|
lines.push('//');
|
|
69
81
|
for (const s of d.sources)
|
|
70
82
|
lines.push(`#define ${d.definePrefix}_FILE_${s.datanameUpperCase}`);
|
|
@@ -74,8 +86,8 @@ const genCommonHeader = (d) => {
|
|
|
74
86
|
return lines.join('\n');
|
|
75
87
|
};
|
|
76
88
|
exports.genCommonHeader = genCommonHeader;
|
|
77
|
-
const genDataArrays = (d,
|
|
78
|
-
const mem =
|
|
89
|
+
const genDataArrays = (d, isProgmem) => {
|
|
90
|
+
const mem = isProgmem ? ' PROGMEM' : '';
|
|
79
91
|
const gzipArrays = d.sources
|
|
80
92
|
.map((s) => `static const uint8_t datagzip_${s.dataname}[${s.lengthGzip}]${mem} = { ${s.bytesGzip} };`)
|
|
81
93
|
.join('\n');
|
|
@@ -142,8 +154,9 @@ const getCppCode = (sources, filesByExtension, options) => {
|
|
|
142
154
|
return transformSourceToTemplateData(s, options.etag, effectiveCacheTime);
|
|
143
155
|
});
|
|
144
156
|
const spaSource = options.spa ? transformedSources.find((s) => s.isDefault) : undefined;
|
|
157
|
+
const routeCount = (0, exports.computeRouteCount)(sources, options.engine, options.basePath, !!options.spa);
|
|
145
158
|
const templateData = {
|
|
146
|
-
config: (0, commandLine_1.
|
|
159
|
+
config: (0, commandLine_1.formatConfig)(options),
|
|
147
160
|
now: (() => {
|
|
148
161
|
const d = new Date();
|
|
149
162
|
return `${d.toLocaleDateString()} ${d.toLocaleTimeString()}`;
|
|
@@ -163,7 +176,8 @@ const getCppCode = (sources, filesByExtension, options) => {
|
|
|
163
176
|
spa: !!options.spa,
|
|
164
177
|
spaSource,
|
|
165
178
|
isPsychic: options.engine === 'psychic',
|
|
166
|
-
|
|
179
|
+
uriHandlers: routeCount.toString(),
|
|
180
|
+
maxUriHandlers: (routeCount + 5).toString()
|
|
167
181
|
};
|
|
168
182
|
return postProcessCppCode(getGenerator(options.engine)(templateData));
|
|
169
183
|
};
|
package/dist/cppCodeEspIdf.js
CHANGED
|
@@ -135,7 +135,7 @@ const genEspIdfCpp = (d) => {
|
|
|
135
135
|
lines.push('//');
|
|
136
136
|
if (d.version)
|
|
137
137
|
lines.push(`#define ${d.definePrefix}_VERSION "${d.version}"`);
|
|
138
|
-
lines.push(`#define ${d.definePrefix}_COUNT ${d.fileCount}`, `#define ${d.definePrefix}_SIZE ${d.fileSize}`, `#define ${d.definePrefix}_SIZE_GZIP ${d.fileGzipSize}`, '//', ...d.sources.map((s) => `#define ${d.definePrefix}_FILE_${s.datanameUpperCase}`), '//', ...d.filesByExtension.map((g) => `#define ${d.definePrefix}_${g.extension}_FILES ${g.count}`), '#include <stdint.h>', '#include <string.h>', '#include <stdlib.h>', '#include <esp_err.h>', '#include <esp_http_server.h>', '//');
|
|
138
|
+
lines.push(`#define ${d.definePrefix}_COUNT ${d.fileCount}`, `#define ${d.definePrefix}_SIZE ${d.fileSize}`, `#define ${d.definePrefix}_SIZE_GZIP ${d.fileGzipSize}`, `#define ${d.definePrefix}_URI_HANDLERS ${d.uriHandlers}`, `#define ${d.definePrefix}_MAX_URI_HANDLERS ${d.maxUriHandlers}`, '//', ...d.sources.map((s) => `#define ${d.definePrefix}_FILE_${s.datanameUpperCase}`), '//', ...d.filesByExtension.map((g) => `#define ${d.definePrefix}_${g.extension}_FILES ${g.count}`), '#include <stdint.h>', '#include <string.h>', '#include <stdlib.h>', '#include <esp_err.h>', '#include <esp_http_server.h>', '//');
|
|
139
139
|
const gzipArrays = d.sources
|
|
140
140
|
.map((s) => `static const unsigned char datagzip_${s.dataname}[${s.lengthGzip}] = { ${s.bytesGzip} };`)
|
|
141
141
|
.join('\n');
|
package/dist/errorMessages.d.ts
CHANGED
|
@@ -2,4 +2,3 @@ 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, espmethod?: string): string;
|
package/dist/errorMessages.js
CHANGED
|
@@ -7,7 +7,6 @@ exports.getMissingIndexError = getMissingIndexError;
|
|
|
7
7
|
exports.getInvalidEngineError = getInvalidEngineError;
|
|
8
8
|
exports.getSourcepathNotFoundError = getSourcepathNotFoundError;
|
|
9
9
|
exports.getSizeBudgetExceededError = getSizeBudgetExceededError;
|
|
10
|
-
exports.getMaxUriHandlersHint = getMaxUriHandlersHint;
|
|
11
10
|
const node_path_1 = __importDefault(require("node:path"));
|
|
12
11
|
const consoleColor_1 = require("./consoleColor");
|
|
13
12
|
function getEngineName(engine) {
|
|
@@ -136,34 +135,3 @@ CI integration:
|
|
|
136
135
|
This non-zero exit code allows build pipelines to fail early when
|
|
137
136
|
the frontend exceeds allocated flash space.`);
|
|
138
137
|
}
|
|
139
|
-
function getMaxUriHandlersHint(engine, routeCount, espmethod = 'initSvelteStaticFiles') {
|
|
140
|
-
const recommended = routeCount + 5;
|
|
141
|
-
const hints = {
|
|
142
|
-
psychic: `PsychicHttpServer server;
|
|
143
|
-
server.config.max_uri_handlers = SVELTEESP32_MAX_URI_HANDLERS; // already defined in the header (${recommended})
|
|
144
|
-
${espmethod}(&server);
|
|
145
|
-
server.listen(80);`,
|
|
146
|
-
espidf: `httpd_config_t config = HTTPD_DEFAULT_CONFIG();
|
|
147
|
-
config.max_uri_handlers = ${recommended}; // Default is 8, you need at least ${routeCount}
|
|
148
|
-
httpd_handle_t server = NULL;
|
|
149
|
-
httpd_start(&server, &config);
|
|
150
|
-
${espmethod}(server);`
|
|
151
|
-
};
|
|
152
|
-
const hint = hints[engine];
|
|
153
|
-
if (!hint)
|
|
154
|
-
return '';
|
|
155
|
-
return ((0, consoleColor_1.yellowLog)('[CONFIG TIP] max_uri_handlers configuration') +
|
|
156
|
-
`
|
|
157
|
-
|
|
158
|
-
Your generated code includes ${routeCount} routes. Make sure your server can handle them:
|
|
159
|
-
|
|
160
|
-
For ${getEngineName(engine)}:
|
|
161
|
-
${hint}
|
|
162
|
-
|
|
163
|
-
Recommended formula: max_uri_handlers = file_count + 5 (safety margin)
|
|
164
|
-
|
|
165
|
-
Runtime symptoms if too low:
|
|
166
|
-
• Routes not registered (HTTP 404 errors)
|
|
167
|
-
• ESP_ERR_HTTPD_HANDLERS_FULL error in logs
|
|
168
|
-
• Some files load, others don't (random behavior)`);
|
|
169
|
-
}
|
package/dist/file.js
CHANGED
|
@@ -29,7 +29,7 @@ const shouldSkipFile = (filename, allFilenames) => {
|
|
|
29
29
|
const extension = node_path_1.default.extname(filename);
|
|
30
30
|
const compressedExtensions = ['.gz', '.brotli', '.br'];
|
|
31
31
|
if (compressedExtensions.includes(extension)) {
|
|
32
|
-
const original = filename.slice(0, -
|
|
32
|
+
const original = filename.slice(0, -extension.length);
|
|
33
33
|
if (allFilenames.includes(original)) {
|
|
34
34
|
console.log((0, consoleColor_1.redLog)(` ${filename} skipped — likely a compressed version of ${original}`));
|
|
35
35
|
return true;
|
package/dist/index.js
CHANGED
|
@@ -7,18 +7,18 @@ const commandLine_1 = require("./commandLine");
|
|
|
7
7
|
const errorMessages_1 = require("./errorMessages");
|
|
8
8
|
const pipeline_1 = require("./pipeline");
|
|
9
9
|
function main() {
|
|
10
|
-
const
|
|
11
|
-
if (!(0, node_fs_1.existsSync)(
|
|
12
|
-
console.error((0, errorMessages_1.getSourcepathNotFoundError)(
|
|
10
|
+
const commandLine = (0, commandLine_1.parseArguments)();
|
|
11
|
+
if (!(0, node_fs_1.existsSync)(commandLine.sourcepath)) {
|
|
12
|
+
console.error((0, errorMessages_1.getSourcepathNotFoundError)(commandLine.sourcepath, 'not_found'));
|
|
13
13
|
process.exit(1);
|
|
14
14
|
}
|
|
15
|
-
if (!(0, node_fs_1.statSync)(
|
|
16
|
-
console.error((0, errorMessages_1.getSourcepathNotFoundError)(
|
|
15
|
+
if (!(0, node_fs_1.statSync)(commandLine.sourcepath).isDirectory()) {
|
|
16
|
+
console.error((0, errorMessages_1.getSourcepathNotFoundError)(commandLine.sourcepath, 'not_directory'));
|
|
17
17
|
process.exit(1);
|
|
18
18
|
}
|
|
19
|
-
console.log(`[SvelteESP32] Generate code for ${
|
|
19
|
+
console.log(`[SvelteESP32] Generate code for ${commandLine.engine} engine`);
|
|
20
20
|
try {
|
|
21
|
-
(0, pipeline_1.runPipeline)(
|
|
21
|
+
(0, pipeline_1.runPipeline)(commandLine);
|
|
22
22
|
}
|
|
23
23
|
catch (error) {
|
|
24
24
|
if (!(error instanceof pipeline_1.OverBudgetError)) {
|
package/dist/pipeline.d.ts
CHANGED
|
@@ -7,12 +7,12 @@ type ProcessingSummary = {
|
|
|
7
7
|
};
|
|
8
8
|
declare const shouldUseGzip: (originalSize: number, compressedSize: number) => boolean;
|
|
9
9
|
declare const calculateCompressionRatio: (originalSize: number, compressedSize: number) => number;
|
|
10
|
-
declare const formatCompressionLog: (filename: string, padding: string, originalSize: number, compressedSize: number,
|
|
10
|
+
declare const formatCompressionLog: (filename: string, padding: string, originalSize: number, compressedSize: number, isGzipUsed: boolean) => string;
|
|
11
11
|
declare const formatSize: (bytes: number) => string;
|
|
12
12
|
declare const formatSizePrecise: (bytes: number) => string;
|
|
13
13
|
declare const createSourceEntry: (filename: string, dataname: string, content: Buffer, contentGzip: Buffer, mimeType: string, sha256: string, isGzip: boolean) => CppCodeSource;
|
|
14
14
|
declare const updateExtensionGroup: (filesByExtension: ExtensionGroups, extension: string) => void;
|
|
15
|
-
declare const formatDryRunRoutes: (sources: CppCodeSources, engine: "psychic" | "async" | "espidf" | "webserver", basePath: string,
|
|
15
|
+
declare const formatDryRunRoutes: (sources: CppCodeSources, engine: "psychic" | "async" | "espidf" | "webserver", basePath: string, isSpa: boolean) => string;
|
|
16
16
|
declare const formatAnalyzeTable: (sources: CppCodeSources, summary: ProcessingSummary, maxSize: number | undefined, maxGzipSize: number | undefined) => string;
|
|
17
17
|
export type PreviousManifestFile = {
|
|
18
18
|
path: string;
|
package/dist/pipeline.js
CHANGED
|
@@ -51,10 +51,10 @@ const shouldUseGzip = (originalSize, compressedSize) => originalSize > GZIP_MIN_
|
|
|
51
51
|
exports.shouldUseGzip = shouldUseGzip;
|
|
52
52
|
const calculateCompressionRatio = (originalSize, compressedSize) => Math.round((compressedSize / originalSize) * 100);
|
|
53
53
|
exports.calculateCompressionRatio = calculateCompressionRatio;
|
|
54
|
-
const formatCompressionLog = (filename, padding, originalSize, compressedSize,
|
|
54
|
+
const formatCompressionLog = (filename, padding, originalSize, compressedSize, isGzipUsed) => {
|
|
55
55
|
const ratio = calculateCompressionRatio(originalSize, compressedSize);
|
|
56
56
|
const sizeInfo = `(${originalSize} -> ${compressedSize} = ${ratio}%)`;
|
|
57
|
-
if (
|
|
57
|
+
if (isGzipUsed)
|
|
58
58
|
return (0, consoleColor_1.greenLog)(` [${filename}] ${padding} ✓ gzip used ${sizeInfo}`);
|
|
59
59
|
const tooSmall = originalSize <= GZIP_MIN_SIZE ? '(too small) ' : '';
|
|
60
60
|
return (0, consoleColor_1.yellowLog)(` [${filename}] ${padding} x gzip unused ${tooSmall}${sizeInfo}`);
|
|
@@ -97,7 +97,7 @@ const sizeCellFor = (s) => {
|
|
|
97
97
|
return `${orig} → ${formatSize(s.contentGzip.length)}`;
|
|
98
98
|
return orig;
|
|
99
99
|
};
|
|
100
|
-
const formatDryRunRoutes = (sources, engine, basePath,
|
|
100
|
+
const formatDryRunRoutes = (sources, engine, basePath, isSpa) => {
|
|
101
101
|
if (sources.length === 0)
|
|
102
102
|
return ' (no files)';
|
|
103
103
|
const defaultSource = sources.find((s) => s.filename === 'index.html' || s.filename === 'index.htm');
|
|
@@ -116,7 +116,7 @@ const formatDryRunRoutes = (sources, engine, basePath, spa) => {
|
|
|
116
116
|
sizeCell: sizeCellFor(source),
|
|
117
117
|
tag: source.isGzip ? '' : '[no gzip]'
|
|
118
118
|
});
|
|
119
|
-
if (
|
|
119
|
+
if (isSpa && defaultSource) {
|
|
120
120
|
const spaUrl = engine === 'psychic' && basePath ? `${basePath}/*` : '(SPA catch-all)';
|
|
121
121
|
rows.push({ url: spaUrl, mime: defaultSource.mime, sizeCell: '', tag: '[SPA catch-all → index.html]' });
|
|
122
122
|
}
|
|
@@ -152,13 +152,13 @@ const formatAnalyzeTable = (sources, summary, maxSize, maxGzipSize) => {
|
|
|
152
152
|
const totalRow = `${'Total'.padEnd(fileWidth)} ${totalOrig.padEnd(origWidth)} ${totalGzip.padEnd(gzipWidth)}`;
|
|
153
153
|
const lines = [header, separator, ...dataRows, separator, totalRow];
|
|
154
154
|
if (maxSize !== undefined) {
|
|
155
|
-
const
|
|
156
|
-
const budgetRow = `${'Budget (maxsize)'.padEnd(fileWidth)} ${formatSizePrecise(maxSize).padEnd(origWidth)} ${'-'.padEnd(gzipWidth)} ${
|
|
155
|
+
const isPass = summary.size <= maxSize;
|
|
156
|
+
const budgetRow = `${'Budget (maxsize)'.padEnd(fileWidth)} ${formatSizePrecise(maxSize).padEnd(origWidth)} ${'-'.padEnd(gzipWidth)} ${isPass ? '✓ PASS' : '✗ FAIL'}`;
|
|
157
157
|
lines.push(budgetRow);
|
|
158
158
|
}
|
|
159
159
|
if (maxGzipSize !== undefined) {
|
|
160
|
-
const
|
|
161
|
-
const budgetRow = `${'Budget (maxgzipsize)'.padEnd(fileWidth)} ${'-'.padEnd(origWidth)} ${formatSizePrecise(maxGzipSize).padEnd(gzipWidth)} ${
|
|
160
|
+
const isPass = summary.gzipsize <= maxGzipSize;
|
|
161
|
+
const budgetRow = `${'Budget (maxgzipsize)'.padEnd(fileWidth)} ${'-'.padEnd(origWidth)} ${formatSizePrecise(maxGzipSize).padEnd(gzipWidth)} ${isPass ? '✓ PASS' : '✗ FAIL'}`;
|
|
162
162
|
lines.push(budgetRow);
|
|
163
163
|
}
|
|
164
164
|
return lines.join('\n');
|
|
@@ -241,19 +241,19 @@ function runPipeline(options) {
|
|
|
241
241
|
updateExtensionGroup(filesByExtension, extension);
|
|
242
242
|
summary.size += content.length;
|
|
243
243
|
const zipContent = (0, node_zlib_1.gzipSync)(content, { level: 9 });
|
|
244
|
-
const
|
|
245
|
-
summary.gzipsize +=
|
|
246
|
-
sources.push(createSourceEntry(filename, dataname, content, zipContent, mimeType, sha256,
|
|
244
|
+
const isUseGzip = shouldUseGzip(content.length, zipContent.length);
|
|
245
|
+
summary.gzipsize += isUseGzip ? zipContent.length : content.length;
|
|
246
|
+
sources.push(createSourceEntry(filename, dataname, content, zipContent, mimeType, sha256, isUseGzip));
|
|
247
247
|
const padding = ' '.repeat(longestFilename - originalFilename.length);
|
|
248
|
-
console.log(formatCompressionLog(originalFilename, padding, content.length, zipContent.length,
|
|
248
|
+
console.log(formatCompressionLog(originalFilename, padding, content.length, zipContent.length, isUseGzip));
|
|
249
249
|
}
|
|
250
250
|
console.log('');
|
|
251
251
|
filesByExtension.sort((left, right) => left.extension.localeCompare(right.extension));
|
|
252
252
|
if (options.analyze) {
|
|
253
253
|
console.log(formatAnalyzeTable(sources, summary, options.maxSize, options.maxGzipSize));
|
|
254
|
-
const
|
|
254
|
+
const isOverBudget = (options.maxSize !== undefined && summary.size > options.maxSize) ||
|
|
255
255
|
(options.maxGzipSize !== undefined && summary.gzipsize > options.maxGzipSize);
|
|
256
|
-
if (
|
|
256
|
+
if (isOverBudget)
|
|
257
257
|
throw new OverBudgetError();
|
|
258
258
|
return;
|
|
259
259
|
}
|
|
@@ -308,6 +308,4 @@ function runPipeline(options) {
|
|
|
308
308
|
if (previousManifest)
|
|
309
309
|
console.log(formatChangeSummary(sources, previousManifest.files));
|
|
310
310
|
}
|
|
311
|
-
if (options.engine === 'psychic' || options.engine === 'espidf')
|
|
312
|
-
console.log('\n' + (0, errorMessages_1.getMaxUriHandlersHint)(options.engine, sources.length, options.espmethod));
|
|
313
311
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "svelteesp32",
|
|
3
|
-
"version": "3.1.
|
|
3
|
+
"version": "3.1.3",
|
|
4
4
|
"description": "Convert Svelte (or any frontend) JS application to serve it from ESP32 webserver (PsychicHttp)",
|
|
5
5
|
"author": "BCsabaEngine",
|
|
6
6
|
"license": "ISC",
|
|
@@ -71,21 +71,21 @@
|
|
|
71
71
|
],
|
|
72
72
|
"devDependencies": {
|
|
73
73
|
"@eslint/js": "^10.0.1",
|
|
74
|
-
"@types/node": "^
|
|
74
|
+
"@types/node": "^26.1.0",
|
|
75
75
|
"@types/picomatch": "^4.0.3",
|
|
76
|
-
"@typescript-eslint/eslint-plugin": "^8.
|
|
77
|
-
"@typescript-eslint/parser": "^8.
|
|
76
|
+
"@typescript-eslint/eslint-plugin": "^8.62.1",
|
|
77
|
+
"@typescript-eslint/parser": "^8.62.1",
|
|
78
78
|
"@vitest/coverage-v8": "^4.1.9",
|
|
79
|
-
"eslint": "^10.
|
|
79
|
+
"eslint": "^10.6.0",
|
|
80
80
|
"eslint-config-prettier": "^10.1.8",
|
|
81
81
|
"eslint-plugin-simple-import-sort": "^13.0.0",
|
|
82
|
-
"eslint-plugin-unicorn": "^
|
|
83
|
-
"globals": "^17.
|
|
84
|
-
"memfs": "^4.57.
|
|
82
|
+
"eslint-plugin-unicorn": "^70.0.0",
|
|
83
|
+
"globals": "^17.7.0",
|
|
84
|
+
"memfs": "^4.57.8",
|
|
85
85
|
"nodemon": "^3.1.14",
|
|
86
|
-
"prettier": "^3.
|
|
86
|
+
"prettier": "^3.9.4",
|
|
87
87
|
"ts-node": "^10.9.2",
|
|
88
|
-
"tsx": "^4.
|
|
88
|
+
"tsx": "^4.23.0",
|
|
89
89
|
"typescript": "^6.0.3",
|
|
90
90
|
"vitest": "^4.1.9"
|
|
91
91
|
},
|