svelteesp32 3.1.1 → 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 +11 -10
- package/dist/commandLine.d.ts +1 -1
- package/dist/commandLine.js +51 -50
- package/dist/consoleColor.js +4 -4
- 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 +5 -3
- package/dist/index.js +7 -7
- package/dist/pipeline.d.ts +2 -2
- package/dist/pipeline.js +18 -19
- package/package.json +13 -13
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`
|
|
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)
|
|
@@ -370,16 +370,16 @@ void initSvelteStaticFiles(PsychicHttpServer * server) {
|
|
|
370
370
|
|
|
371
371
|
## Supported Web Server Engines
|
|
372
372
|
|
|
373
|
-
| Engine | Flag | Best For | Platform |
|
|
374
|
-
| ------------------------ | -------------- | ---------------------------- | --------------- |
|
|
375
|
-
| **PsychicHttpServer V2** | `-e psychic` | Maximum performance | ESP32 only |
|
|
376
|
-
| **ESPAsyncWebServer** | `-e async` | Cross-platform compatibility | ESP32 + ESP8266 |
|
|
377
|
-
| **Arduino WebServer** | `-e webserver` | No dependencies, simplicity | ESP32 only |
|
|
378
|
-
| **Native ESP-IDF** | `-e espidf` | Pure ESP-IDF projects | ESP32 only |
|
|
373
|
+
| Engine | Flag | Best For | Platform | Library |
|
|
374
|
+
| ------------------------ | -------------- | ---------------------------- | --------------- | ---------------------------------------------------------------------------- |
|
|
375
|
+
| **PsychicHttpServer V2** | `-e psychic` | Maximum performance | ESP32 only | [PsychicHttp 2.2.0, 3.1.1](https://github.com/hoeken/PsychicHttp) |
|
|
376
|
+
| **ESPAsyncWebServer** | `-e async` | Cross-platform compatibility | ESP32 + ESP8266 | [ESPAsyncWebServer v3.11.1](https://github.com/ESP32Async/ESPAsyncWebServer) |
|
|
377
|
+
| **Arduino WebServer** | `-e webserver` | No dependencies, simplicity | ESP32 only | (built-in) |
|
|
378
|
+
| **Native ESP-IDF** | `-e espidf` | Pure ESP-IDF projects | ESP32 only | (built-in) |
|
|
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
|
|
|
@@ -745,7 +745,7 @@ platform = espressif32
|
|
|
745
745
|
board = esp32dev
|
|
746
746
|
framework = arduino
|
|
747
747
|
lib_deps =
|
|
748
|
-
|
|
748
|
+
https://github.com/ESP32Async/ESPAsyncWebServer#v3.11.1
|
|
749
749
|
extra_scripts = pre:scripts/build_frontend.py
|
|
750
750
|
```
|
|
751
751
|
|
|
@@ -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"));
|
|
@@ -77,13 +77,13 @@ RC File:
|
|
|
77
77
|
process.exit(0);
|
|
78
78
|
}
|
|
79
79
|
function validateEngine(value) {
|
|
80
|
-
if (
|
|
80
|
+
if (['psychic', 'async', 'espidf', 'webserver'].includes(value))
|
|
81
81
|
return value;
|
|
82
82
|
console.error((0, errorMessages_1.getInvalidEngineError)(value));
|
|
83
83
|
process.exit(1);
|
|
84
84
|
}
|
|
85
85
|
function validateTriState(value, name) {
|
|
86
|
-
if (
|
|
86
|
+
if (['always', 'never', 'compiler'].includes(value))
|
|
87
87
|
return value;
|
|
88
88
|
throw new Error(`Invalid ${name}: ${value}`);
|
|
89
89
|
}
|
|
@@ -117,7 +117,7 @@ function parseSize(value, name) {
|
|
|
117
117
|
const match = trimmed.match(/^(\d+(?:\.\d+)?)\s*([KMkm])?$/);
|
|
118
118
|
if (!match || !match[1])
|
|
119
119
|
throw new Error(`${name} must be a positive number with optional k/K (×1024) or m/M (×1024²) suffix: ${value}`);
|
|
120
|
-
const numericPart = Number
|
|
120
|
+
const numericPart = Number(match[1]);
|
|
121
121
|
const suffix = match[2]?.toLowerCase();
|
|
122
122
|
let bytes;
|
|
123
123
|
if (suffix === 'k')
|
|
@@ -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
|
}
|
|
@@ -385,7 +386,7 @@ function parseArguments() {
|
|
|
385
386
|
const argument = arguments_[index];
|
|
386
387
|
if (!argument)
|
|
387
388
|
continue;
|
|
388
|
-
if (argument === '--config' && arguments_[index + 1]) {
|
|
389
|
+
if (argument === '--config' && arguments_[index + 1] !== undefined) {
|
|
389
390
|
customConfigPath = arguments_[index + 1];
|
|
390
391
|
break;
|
|
391
392
|
}
|
|
@@ -395,12 +396,12 @@ function parseArguments() {
|
|
|
395
396
|
}
|
|
396
397
|
}
|
|
397
398
|
const rcPath = findRcFile(customConfigPath);
|
|
398
|
-
const rcConfig = rcPath ? loadRcFile(rcPath) : {};
|
|
399
399
|
if (rcPath) {
|
|
400
400
|
console.log((0, consoleColor_1.cyanLog)(`[SvelteESP32] Using config from: ${rcPath}`));
|
|
401
401
|
if (!customConfigPath && node_path_1.default.dirname(rcPath) === process.cwd())
|
|
402
402
|
console.warn((0, consoleColor_1.yellowLog)(`Warning: Loading config from current directory — verify this file is trusted before proceeding.`));
|
|
403
403
|
}
|
|
404
|
+
const rcConfig = rcPath ? loadRcFile(rcPath) : {};
|
|
404
405
|
const result = {
|
|
405
406
|
engine: 'psychic',
|
|
406
407
|
outputfile: 'svelteesp32.h',
|
|
@@ -487,14 +488,14 @@ function parseArguments() {
|
|
|
487
488
|
result.define = validateCppIdentifier(value, 'define');
|
|
488
489
|
break;
|
|
489
490
|
case 'cachetime':
|
|
490
|
-
result.cachetime =
|
|
491
|
+
result.cachetime = Math.trunc(Number(value));
|
|
491
492
|
if (Number.isNaN(result.cachetime))
|
|
492
493
|
throw new TypeError(`Invalid cachetime: ${value}`);
|
|
493
494
|
if (result.cachetime < 0)
|
|
494
495
|
throw new TypeError(`Invalid cachetime: ${value} (must be non-negative)`);
|
|
495
496
|
break;
|
|
496
497
|
case 'cachetimehtml': {
|
|
497
|
-
result.cachetimeHtml =
|
|
498
|
+
result.cachetimeHtml = Math.trunc(Number(value));
|
|
498
499
|
if (Number.isNaN(result.cachetimeHtml))
|
|
499
500
|
throw new TypeError(`Invalid cachetimehtml: ${value}`);
|
|
500
501
|
if (result.cachetimeHtml < 0)
|
|
@@ -502,7 +503,7 @@ function parseArguments() {
|
|
|
502
503
|
break;
|
|
503
504
|
}
|
|
504
505
|
case 'cachetimeassets': {
|
|
505
|
-
result.cachetimeAssets =
|
|
506
|
+
result.cachetimeAssets = Math.trunc(Number(value));
|
|
506
507
|
if (Number.isNaN(result.cachetimeAssets))
|
|
507
508
|
throw new TypeError(`Invalid cachetimeassets: ${value}`);
|
|
508
509
|
if (result.cachetimeAssets < 0)
|
|
@@ -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/consoleColor.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.cyanLog = exports.redLog = exports.yellowLog = exports.greenLog = void 0;
|
|
4
|
-
const greenLog = (s) => `\
|
|
4
|
+
const greenLog = (s) => `\u{1B}[32m${s}\u{1B}[0m`;
|
|
5
5
|
exports.greenLog = greenLog;
|
|
6
|
-
const yellowLog = (s) => `\
|
|
6
|
+
const yellowLog = (s) => `\u{1B}[33m${s}\u{1B}[0m`;
|
|
7
7
|
exports.yellowLog = yellowLog;
|
|
8
|
-
const redLog = (s) => `\
|
|
8
|
+
const redLog = (s) => `\u{1B}[31m${s}\u{1B}[0m`;
|
|
9
9
|
exports.redLog = redLog;
|
|
10
|
-
const cyanLog = (s) => `\
|
|
10
|
+
const cyanLog = (s) => `\u{1B}[36m${s}\u{1B}[0m`;
|
|
11
11
|
exports.cyanLog = cyanLog;
|
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
|
@@ -12,7 +12,7 @@ const consoleColor_1 = require("./consoleColor");
|
|
|
12
12
|
const errorMessages_1 = require("./errorMessages");
|
|
13
13
|
const findSimilarFiles = (files) => {
|
|
14
14
|
const contentComparer = new Map();
|
|
15
|
-
for (const [filename, fileData] of files
|
|
15
|
+
for (const [filename, fileData] of files) {
|
|
16
16
|
const existingFiles = contentComparer.get(fileData.hash);
|
|
17
17
|
if (existingFiles)
|
|
18
18
|
existingFiles.push(filename);
|
|
@@ -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;
|
|
@@ -88,7 +88,9 @@ const getFiles = (options) => {
|
|
|
88
88
|
const duplicates = findSimilarFiles(result);
|
|
89
89
|
for (const sameFiles of duplicates)
|
|
90
90
|
console.log((0, consoleColor_1.yellowLog)(` ${sameFiles.join(', ')} files appear identical`));
|
|
91
|
-
const hasIndex =
|
|
91
|
+
const hasIndex = result
|
|
92
|
+
.keys()
|
|
93
|
+
.some((f) => f === 'index.html' || f === 'index.htm' || f.endsWith('/index.html') || f.endsWith('/index.htm'));
|
|
92
94
|
if (!hasIndex && !options.noIndexCheck)
|
|
93
95
|
throw new Error((0, errorMessages_1.getMissingIndexError)(options.engine));
|
|
94
96
|
return result;
|
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');
|
|
@@ -219,11 +219,11 @@ function runPipeline(options) {
|
|
|
219
219
|
const files = (0, file_1.getFiles)(options);
|
|
220
220
|
if (files.size === 0)
|
|
221
221
|
throw new Error(`Directory ${options.sourcepath} is empty`);
|
|
222
|
-
if (options.spa &&
|
|
222
|
+
if (options.spa && files.keys().every((f) => !(f === 'index.html' || f === 'index.htm')))
|
|
223
223
|
console.warn((0, consoleColor_1.yellowLog)('[SvelteESP32] Warning: --spa is set but no index.html/index.htm found; catch-all will not be generated.'));
|
|
224
224
|
console.log();
|
|
225
225
|
console.log('Translation to header file');
|
|
226
|
-
const longestFilename =
|
|
226
|
+
const longestFilename = files.keys().reduce((p, c) => Math.max(c.length, p), 0);
|
|
227
227
|
for (const [originalFilename, fileData] of files) {
|
|
228
228
|
const { content, hash: sha256 } = fileData;
|
|
229
229
|
const rawMime = mimeLookup(originalFilename);
|
|
@@ -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
|
}
|
|
@@ -285,8 +285,9 @@ function runPipeline(options) {
|
|
|
285
285
|
}
|
|
286
286
|
catch {
|
|
287
287
|
}
|
|
288
|
+
const now = new Date();
|
|
288
289
|
const manifest = {
|
|
289
|
-
generated:
|
|
290
|
+
generated: now.toISOString(),
|
|
290
291
|
engine: options.engine,
|
|
291
292
|
etag: options.etag,
|
|
292
293
|
gzip: options.gzip,
|
|
@@ -307,6 +308,4 @@ function runPipeline(options) {
|
|
|
307
308
|
if (previousManifest)
|
|
308
309
|
console.log(formatChangeSummary(sources, previousManifest.files));
|
|
309
310
|
}
|
|
310
|
-
if (options.engine === 'psychic' || options.engine === 'espidf')
|
|
311
|
-
console.log('\n' + (0, errorMessages_1.getMaxUriHandlersHint)(options.engine, sources.length, options.espmethod));
|
|
312
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,23 +71,23 @@
|
|
|
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.
|
|
78
|
-
"@vitest/coverage-v8": "^4.1.
|
|
79
|
-
"eslint": "^10.
|
|
76
|
+
"@typescript-eslint/eslint-plugin": "^8.62.1",
|
|
77
|
+
"@typescript-eslint/parser": "^8.62.1",
|
|
78
|
+
"@vitest/coverage-v8": "^4.1.9",
|
|
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
|
-
"vitest": "^4.1.
|
|
90
|
+
"vitest": "^4.1.9"
|
|
91
91
|
},
|
|
92
92
|
"peerDependencies": {
|
|
93
93
|
"vite": ">=5"
|
|
@@ -98,6 +98,6 @@
|
|
|
98
98
|
}
|
|
99
99
|
},
|
|
100
100
|
"dependencies": {
|
|
101
|
-
"tinyglobby": "^0.2.
|
|
101
|
+
"tinyglobby": "^0.2.17"
|
|
102
102
|
}
|
|
103
103
|
}
|