svelteesp32 1.8.0 → 1.9.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 CHANGED
@@ -10,7 +10,9 @@ I often make small to medium-sized microcontroller solutions that run on ESP32 o
10
10
 
11
11
  In order to be able to easily update OTA, it is important - from the users' point of view - that the update file **consists of one file**. I can't use the SPIFFS/LittleFS solution for this. It is necessary that the WebUI files are included inline in the Arduino or PlatformIO c++ code.
12
12
 
13
- This npm package provides a solution for **inserting any JS client application into the ESP web server** (PsychicHttp and also ESPAsyncWebServer (https://github.com/ESP32Async/ESPAsyncWebServer) available, PsychicHttp is the default). For this, JS, html, css, font, assets, etc. files must be converted to binary byte array. Npm mode is easy to use and easy to **integrate into your CI/CD pipeline**.
13
+ This npm package provides a solution for **inserting any JS client application into the ESP web server** (PsychicHttp and also ESPAsyncWebServer (https://github.com/ESP32Async/ESPAsyncWebServer) and ESP-IDF available, PsychicHttp is the default). For this, JS, html, css, font, assets, etc. files must be converted to binary byte array. Npm mode is easy to use and easy to **integrate into your CI/CD pipeline**.
14
+
15
+ > Starting with version v1.9.0, code generator for esp-idf is available
14
16
 
15
17
  > Starting with version v1.8.0, use the new and maintained ESPAsyncWebserver available at https://github.com/ESP32Async/ESPAsyncWebServer
16
18
 
@@ -47,6 +49,9 @@ npx svelteesp32 -e psychic2 -s ../svelteapp/dist -o ../esp32project/svelteesp32.
47
49
 
48
50
  // for ESPAsyncWebServer
49
51
  npx svelteesp32 -e async -s ../svelteapp/dist -o ../esp32project/svelteesp32.h --etag=true
52
+
53
+ // for native esp-idf
54
+ npx svelteesp32 -e espidf -s ../svelteapp/dist -o ../esp32project/svelteesp32.h --etag=true
50
55
  ```
51
56
 
52
57
  During the **translation process**, the processed file details are visible, and at the end, the result shows the ESP's memory allocation (gzip size)
@@ -1,5 +1,5 @@
1
1
  interface ICopyFilesArguments {
2
- engine: 'psychic' | 'psychic2' | 'async';
2
+ engine: 'psychic' | 'psychic2' | 'async' | 'espidf';
3
3
  sourcepath: string;
4
4
  outputfile: string;
5
5
  espmethod: string;
@@ -12,6 +12,8 @@ exports.cmdLine = (0, ts_command_line_args_1.parse)({
12
12
  return 'psychic2';
13
13
  if (value === 'async')
14
14
  return 'async';
15
+ if (value === 'espidf')
16
+ return 'espidf';
15
17
  throw new Error(`Invalid engine: ${value}`);
16
18
  },
17
19
  alias: 'e',
package/dist/cppCode.js CHANGED
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getCppCode = void 0;
4
4
  const handlebars_1 = require("handlebars");
5
5
  const commandLine_1 = require("./commandLine");
6
+ const cppCodeEspIdf_1 = require("./cppCodeEspIdf");
6
7
  const psychicTemplate = `
7
8
  //engine: PsychicHttpServer
8
9
  //cmdline: {{{commandLine}}}
@@ -152,20 +153,20 @@ void {{methodName}}(PsychicHttpServer * server) {
152
153
  {{#switch ../etag}}
153
154
  {{#case "true"}}
154
155
  {{#../cacheTime}}
155
- response.addHeader("cache-control", "max-age={{value}}");
156
+ response.addHeader("Cache-Control", "max-age={{value}}");
156
157
  {{/../cacheTime}}
157
158
  {{^../cacheTime}}
158
- response.addHeader("cache-control", "no-cache");
159
+ response.addHeader("Cache-Control", "no-cache");
159
160
  {{/../cacheTime}}
160
161
  response.addHeader("ETag", etag_{{this.dataname}});
161
162
  {{/case}}
162
163
  {{#case "compiler"}}
163
164
  #ifdef {{../definePrefix}}_ENABLE_ETAG
164
165
  {{#../cacheTime}}
165
- response.addHeader("cache-control", "max-age={{value}}");
166
+ response.addHeader("Cache-Control", "max-age={{value}}");
166
167
  {{/../cacheTime}}
167
168
  {{^../cacheTime}}
168
- response.addHeader("cache-control", "no-cache");
169
+ response.addHeader("Cache-Control", "no-cache");
169
170
  {{/../cacheTime}}
170
171
  response.addHeader("ETag", etag_{{this.dataname}});
171
172
  #endif
@@ -338,20 +339,20 @@ void {{methodName}}(PsychicHttpServer * server) {
338
339
  {{#switch ../etag}}
339
340
  {{#case "true"}}
340
341
  {{#../cacheTime}}
341
- response->addHeader("cache-control", "max-age={{value}}");
342
+ response->addHeader("Cache-Control", "max-age={{value}}");
342
343
  {{/../cacheTime}}
343
344
  {{^../cacheTime}}
344
- response->addHeader("cache-control", "no-cache");
345
+ response->addHeader("Cache-Control", "no-cache");
345
346
  {{/../cacheTime}}
346
347
  response->addHeader("ETag", etag_{{this.dataname}});
347
348
  {{/case}}
348
349
  {{#case "compiler"}}
349
350
  #ifdef {{../definePrefix}}_ENABLE_ETAG
350
351
  {{#../cacheTime}}
351
- response->addHeader("cache-control", "max-age={{value}}");
352
+ response->addHeader("Cache-Control", "max-age={{value}}");
352
353
  {{/../cacheTime}}
353
354
  {{^../cacheTime}}
354
- response->addHeader("cache-control", "no-cache");
355
+ response->addHeader("Cache-Control", "no-cache");
355
356
  {{/../cacheTime}}
356
357
  response->addHeader("ETag", etag_{{this.dataname}});
357
358
  #endif
@@ -528,20 +529,20 @@ void {{methodName}}(AsyncWebServer * server) {
528
529
  {{#switch ../etag}}
529
530
  {{#case "true"}}
530
531
  {{#../cacheTime}}
531
- response->addHeader("cache-control", "max-age={{value}}");
532
+ response->addHeader("Cache-Control", "max-age={{value}}");
532
533
  {{/../cacheTime}}
533
534
  {{^../cacheTime}}
534
- response->addHeader("cache-control", "no-cache");
535
+ response->addHeader("Cache-Control", "no-cache");
535
536
  {{/../cacheTime}}
536
537
  response->addHeader("ETag", etag_{{this.dataname}});
537
538
  {{/case}}
538
539
  {{#case "compiler"}}
539
540
  #ifdef {{../definePrefix}}_ENABLE_ETAG
540
541
  {{#../cacheTime}}
541
- response->addHeader("cache-control", "max-age={{value}}");
542
+ response->addHeader("Cache-Control", "max-age={{value}}");
542
543
  {{/../cacheTime}}
543
544
  {{^../cacheTime}}
544
- response->addHeader("cache-control", "no-cache");
545
+ response->addHeader("Cache-Control", "no-cache");
545
546
  {{/../cacheTime}}
546
547
  response->addHeader("ETag", etag_{{this.dataname}});
547
548
  #endif
@@ -557,8 +558,20 @@ void {{methodName}}(AsyncWebServer * server) {
557
558
 
558
559
  {{/each}}
559
560
  }`;
561
+ const getTemplate = (engine) => {
562
+ switch (engine) {
563
+ case 'psychic':
564
+ return psychicTemplate;
565
+ case 'psychic2':
566
+ return psychic2Template;
567
+ case 'espidf':
568
+ return cppCodeEspIdf_1.espidfTemplate;
569
+ default:
570
+ return asyncTemplate;
571
+ }
572
+ };
560
573
  let switchValue;
561
- const getCppCode = (sources, filesByExtension) => (0, handlebars_1.compile)(commandLine_1.cmdLine.engine === 'psychic' ? psychicTemplate : commandLine_1.cmdLine.engine === 'psychic2' ? psychic2Template : asyncTemplate)({
574
+ const getCppCode = (sources, filesByExtension) => (0, handlebars_1.compile)(getTemplate(commandLine_1.cmdLine.engine))({
562
575
  commandLine: process.argv.slice(2).join(' '),
563
576
  now: `${new Date().toLocaleDateString()} ${new Date().toLocaleTimeString()}`,
564
577
  fileCount: sources.length.toString(),
@@ -0,0 +1 @@
1
+ export declare const espidfTemplate = "\n//engine: espidf\n//cmdline: {{{commandLine}}}\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 <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}}\nconst char * etag_{{this.dataname}} = \"{{this.md5}}\";\n {{/each}}\n{{/case}}\n{{#case \"false\"}}\n{{/case}}\n{{#case \"compiler\"}}\n#ifdef {{definePrefix}}_ENABLE_ETAG\n {{#each sources}}\nconst char * etag_{{this.dataname}} = \"{{this.md5}}\";\n {{/each}}\n#endif \n{{/case}}\n{{/switch}}\n\n{{#each sources}}\n\nstatic esp_err_t file_handler_{{this.datanameUpperCase}} (httpd_req_t *req)\n{\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 \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 = \"/\",\n .method = HTTP_GET,\n .handler = file_handler_{{this.datanameUpperCase}},\n};\n{{/if}}\n\nstatic const httpd_uri_t route_{{this.datanameUpperCase}} = {\n .uri = \"/{{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}";
@@ -0,0 +1,190 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.espidfTemplate = void 0;
4
+ exports.espidfTemplate = `
5
+ //engine: espidf
6
+ //cmdline: {{{commandLine}}}
7
+ {{#if created }}
8
+ //created: {{now}}
9
+ {{/if}}
10
+ //
11
+
12
+ {{#switch etag}}
13
+ {{#case "true"}}
14
+ #ifdef {{definePrefix}}_ENABLE_ETAG
15
+ #warning {{definePrefix}}_ENABLE_ETAG has no effect because it is permanently switched ON
16
+ #endif
17
+ {{/case}}
18
+ {{#case "false"}}
19
+ #ifdef {{definePrefix}}_ENABLE_ETAG
20
+ #warning {{definePrefix}}_ENABLE_ETAG has no effect because it is permanently switched OFF
21
+ #endif
22
+ {{/case}}
23
+ {{/switch}}
24
+
25
+ {{#switch gzip}}
26
+ {{#case "true"}}
27
+ #ifdef {{definePrefix}}_ENABLE_GZIP
28
+ #warning {{definePrefix}}_ENABLE_GZIP has no effect because it is permanently switched ON
29
+ #endif
30
+ {{/case}}
31
+ {{#case "false"}}
32
+ #ifdef {{definePrefix}}_ENABLE_GZIP
33
+ #warning {{definePrefix}}_ENABLE_GZIP has no effect because it is permanently switched OFF
34
+ #endif
35
+ {{/case}}
36
+ {{/switch}}
37
+
38
+ //
39
+ {{#if version }}
40
+ #define {{definePrefix}}_VERSION "{{version}}"
41
+ {{/if}}
42
+ #define {{definePrefix}}_COUNT {{fileCount}}
43
+ #define {{definePrefix}}_SIZE {{fileSize}}
44
+ #define {{definePrefix}}_SIZE_GZIP {{fileGzipSize}}
45
+
46
+ //
47
+ {{#each sources}}
48
+ #define {{../definePrefix}}_FILE_{{this.datanameUpperCase}}
49
+ {{/each}}
50
+
51
+ //
52
+ {{#each filesByExtension}}
53
+ #define {{../definePrefix}}_{{this.extension}}_FILES {{this.count}}
54
+ {{/each}}
55
+
56
+ #include <stdint.h>
57
+ #include <esp_err.h>
58
+ #include <esp_http_server.h>
59
+
60
+ //
61
+ {{#switch gzip}}
62
+ {{#case "true"}}
63
+ {{#each sources}}
64
+ const char datagzip_{{this.dataname}}[{{this.lengthGzip}}] = { {{this.bytesGzip}} };
65
+ {{/each}}
66
+ {{/case}}
67
+ {{#case "false"}}
68
+ {{#each sources}}
69
+ const char data_{{this.dataname}}[{{this.length}}] = { {{this.bytes}} };
70
+ {{/each}}
71
+ {{/case}}
72
+ {{#case "compiler"}}
73
+ #ifdef {{definePrefix}}_ENABLE_GZIP
74
+ {{#each sources}}
75
+ const char datagzip_{{this.dataname}}[{{this.lengthGzip}}] = { {{this.bytesGzip}} };
76
+ {{/each}}
77
+ #else
78
+ {{#each sources}}
79
+ const char data_{{this.dataname}}[{{this.length}}] = { {{this.bytes}} };
80
+ {{/each}}
81
+ #endif
82
+ {{/case}}
83
+ {{/switch}}
84
+
85
+ //
86
+ {{#switch etag}}
87
+ {{#case "true"}}
88
+ {{#each sources}}
89
+ const char * etag_{{this.dataname}} = "{{this.md5}}";
90
+ {{/each}}
91
+ {{/case}}
92
+ {{#case "false"}}
93
+ {{/case}}
94
+ {{#case "compiler"}}
95
+ #ifdef {{definePrefix}}_ENABLE_ETAG
96
+ {{#each sources}}
97
+ const char * etag_{{this.dataname}} = "{{this.md5}}";
98
+ {{/each}}
99
+ #endif
100
+ {{/case}}
101
+ {{/switch}}
102
+
103
+ {{#each sources}}
104
+
105
+ static esp_err_t file_handler_{{this.datanameUpperCase}} (httpd_req_t *req)
106
+ {
107
+ httpd_resp_set_type(req, "{{this.mime}}");
108
+ {{#switch ../gzip}}
109
+ {{#case "true"}}
110
+ {{#if this.isGzip}}
111
+ httpd_resp_set_hdr(req, "Content-Encoding", "gzip");
112
+ {{/if}}
113
+ {{/case}}
114
+ {{#case "compiler"}}
115
+ {{#if this.isGzip}}
116
+ #ifdef {{../definePrefix}}_ENABLE_GZIP
117
+ httpd_resp_set_hdr(req, "Content-Encoding", "gzip");
118
+ #endif
119
+ {{/if}}
120
+ {{/case}}
121
+ {{/switch}}
122
+
123
+ {{#switch ../etag}}
124
+ {{#case "true"}}
125
+ {{#../cacheTime}}
126
+ httpd_resp_set_hdr(req, "Cache-Control", "max-age={{value}}");
127
+ {{/../cacheTime}}
128
+ {{^../cacheTime}}
129
+ httpd_resp_set_hdr(req, "Cache-Control", "no-cache");
130
+ {{/../cacheTime}}
131
+ httpd_resp_set_hdr(req, "ETag", etag_{{this.dataname}});
132
+ {{/case}}
133
+ {{#case "compiler"}}
134
+ #ifdef {{../definePrefix}}_ENABLE_ETAG
135
+ {{#../cacheTime}}
136
+ httpd_resp_set_hdr(req, "Cache-Control", "max-age={{value}}");
137
+ {{/../cacheTime}}
138
+ {{^../cacheTime}}
139
+ httpd_resp_set_hdr(req, "Cache-Control", "no-cache");
140
+ {{/../cacheTime}}
141
+ httpd_resp_set_hdr(req, "ETag", etag_{{this.dataname}});
142
+ #endif
143
+ {{/case}}
144
+ {{/switch}}
145
+
146
+ {{#switch ../gzip}}
147
+ {{#case "true"}}
148
+ httpd_resp_send(req, datagzip_{{this.dataname}}, {{this.lengthGzip}});
149
+ {{/case}}
150
+ {{#case "false"}}
151
+ httpd_resp_send(req, data_{{this.dataname}}, {{this.length}});
152
+ {{/case}}
153
+ {{#case "compiler"}}
154
+ #ifdef {{../definePrefix}}_ENABLE_GZIP
155
+ httpd_resp_send(req, datagzip_{{this.dataname}}, {{this.lengthGzip}});
156
+ #else
157
+ httpd_resp_send(req, data_{{this.dataname}}, {{this.length}});
158
+ #endif
159
+ {{/case}}
160
+ {{/switch}}
161
+ return ESP_OK;
162
+ }
163
+
164
+ {{#if this.isDefault}}
165
+ static const httpd_uri_t route_def_{{this.datanameUpperCase}} = {
166
+ .uri = "/",
167
+ .method = HTTP_GET,
168
+ .handler = file_handler_{{this.datanameUpperCase}},
169
+ };
170
+ {{/if}}
171
+
172
+ static const httpd_uri_t route_{{this.datanameUpperCase}} = {
173
+ .uri = "/{{this.filename}}",
174
+ .method = HTTP_GET,
175
+ .handler = file_handler_{{this.datanameUpperCase}},
176
+ };
177
+
178
+ {{/each}}
179
+
180
+
181
+
182
+ static inline void {{methodName}}(httpd_handle_t server) {
183
+ {{#each sources}}
184
+ {{#if this.isDefault}}
185
+ httpd_register_uri_handler(server, &route_def_{{this.datanameUpperCase}});
186
+ {{/if}}
187
+ httpd_register_uri_handler(server, &route_{{this.datanameUpperCase}});
188
+ {{/each}}
189
+
190
+ }`;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "svelteesp32",
3
- "version": "1.8.0",
3
+ "version": "1.9.0",
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",
@@ -31,7 +31,7 @@
31
31
  "dev:async": "nodemon src/index.ts -- -e async -s ./demo/svelte/dist -o ./demo/esp32/include/svelteesp32.h --etag=true --gzip=true --cachetime=86400 --version=v$npm_package_version",
32
32
  "dev:psychic": "nodemon src/index.ts -- -e psychic -s ./demo/svelte/dist -o ./demo/esp32/include/svelteesp32.h --etag=false --gzip=false --version=v$npm_package_version",
33
33
  "dev:psychic2": "nodemon src/index.ts -- -e psychic2 -s ./demo/svelte/dist -o ./demo/esp32/include/svelteesp32.h --etag=false --gzip=false --version=v$npm_package_version",
34
- "test:all": "./package.script && ~/.platformio/penv/bin/pio run -d ./demo/esp32",
34
+ "test:all": "./package.script && ~/.platformio/penv/bin/pio run -d ./demo/esp32 && ~/.platformio/penv/bin/pio run -d ./demo/esp32idf",
35
35
  "clean": "tsc --build --clean",
36
36
  "build": "tsc --build --clean && tsc --build --force",
37
37
  "format:check": "prettier --check .",
@@ -55,23 +55,23 @@
55
55
  ],
56
56
  "devDependencies": {
57
57
  "@types/mime-types": "^2.1.4",
58
- "@types/node": "^22.13.4",
59
- "@typescript-eslint/eslint-plugin": "^8.24.1",
60
- "@typescript-eslint/parser": "^8.24.1",
61
- "eslint": "^9.20.1",
62
- "eslint-config-prettier": "^10.0.1",
58
+ "@types/node": "^22.13.14",
59
+ "@typescript-eslint/eslint-plugin": "^8.29.0",
60
+ "@typescript-eslint/parser": "^8.29.0",
61
+ "eslint": "^9.23.0",
62
+ "eslint-config-prettier": "^10.1.1",
63
63
  "eslint-plugin-simple-import-sort": "^12.1.1",
64
- "eslint-plugin-unicorn": "^57.0.0",
64
+ "eslint-plugin-unicorn": "^58.0.0",
65
65
  "nodemon": "^3.1.9",
66
- "prettier": "^3.5.1",
66
+ "prettier": "^3.5.3",
67
67
  "ts-node": "^10.9.2",
68
68
  "tsx": "^4.19.3",
69
- "typescript": "^5.7.3"
69
+ "typescript": "^5.8.2"
70
70
  },
71
71
  "dependencies": {
72
72
  "glob": "^11.0.1",
73
73
  "handlebars": "^4.7.8",
74
- "mime-types": "^2.1.35",
74
+ "mime-types": "^3.0.1",
75
75
  "ts-command-line-args": "^2.5.1"
76
76
  }
77
77
  }