svelteesp32 1.3.0 → 1.4.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 +56 -36
- package/dist/commandLine.d.ts +4 -2
- package/dist/commandLine.js +33 -7
- package/dist/consoleColor.d.ts +3 -0
- package/dist/consoleColor.js +9 -0
- package/dist/cppCode.d.ts +10 -2
- package/dist/cppCode.js +313 -35
- package/dist/file.js +16 -3
- package/dist/index.js +41 -42
- package/package.json +5 -9
package/README.md
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# `svelteesp32` 
|
|
2
2
|
|
|
3
|
+
[Changelog](CHANGELOG.md)
|
|
4
|
+
|
|
3
5
|
# Convert Svelte (or React/Angular/Vue) JS application to serve it from ESP32/ESP8266 webserver
|
|
4
6
|
|
|
5
7
|
### Forget SPIFFS and LittleFS now
|
|
@@ -10,11 +12,13 @@ In order to be able to easily update OTA, it is important - from the users' poin
|
|
|
10
12
|
|
|
11
13
|
This npm package provides a solution for **inserting any JS client application into the ESP web server** (PsychicHttp and also 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**.
|
|
12
14
|
|
|
13
|
-
> Starting with version
|
|
15
|
+
> Version v1.4.0 has a breaking change! --no-gzip changed to --gzip. Starting with this version c++ compiler directives are available to setup operation in project level.
|
|
16
|
+
|
|
17
|
+
> Starting with version v1.3.0, c++ defines can be used.
|
|
14
18
|
|
|
15
19
|
> Starting with version v1.2.0, ESP8266/ESP8285 is also supported.
|
|
16
20
|
|
|
17
|
-
> Starting with version v1.
|
|
21
|
+
> Starting with version v1.1.0, the ETag header is also supported.
|
|
18
22
|
|
|
19
23
|
### Usage
|
|
20
24
|
|
|
@@ -28,29 +32,20 @@ After a successful Svelte build (rollup/webpack/vite) **create an includeable c+
|
|
|
28
32
|
|
|
29
33
|
```bash
|
|
30
34
|
// for PsychicHttpServer
|
|
31
|
-
npx svelteesp32 -e psychic -s ../svelteapp/dist -o ../esp32project/svelteesp32.h --etag
|
|
35
|
+
npx svelteesp32 -e psychic -s ../svelteapp/dist -o ../esp32project/svelteesp32.h --etag=true
|
|
32
36
|
|
|
33
37
|
// for ESPAsyncWebServer
|
|
34
|
-
npx svelteesp32 -e async -s ../svelteapp/dist -o ../esp32project/svelteesp32.h --etag
|
|
38
|
+
npx svelteesp32 -e async -s ../svelteapp/dist -o ../esp32project/svelteesp32.h --etag=true
|
|
35
39
|
```
|
|
36
40
|
|
|
37
41
|
During the **translation process**, the processed file details are visible, and at the end, the result shows the ESP's memory allocation (gzip size)
|
|
38
42
|
|
|
39
43
|
```
|
|
40
|
-
[assets/index-KwubEIf-.js]
|
|
41
|
-
✓ gzip used (
|
|
42
|
-
|
|
43
|
-
[
|
|
44
|
-
✓ gzip used (
|
|
45
|
-
|
|
46
|
-
[favicon.png]
|
|
47
|
-
x gzip unused (33249 -> 33282)
|
|
48
|
-
|
|
49
|
-
[index.html]
|
|
50
|
-
✓ gzip used (472 -> 308)
|
|
51
|
-
|
|
52
|
-
[roboto_regular.json]
|
|
53
|
-
✓ gzip used (363757 -> 93567)
|
|
44
|
+
[assets/index-KwubEIf-.js] ✓ gzip used (38850 -> 12547)
|
|
45
|
+
[assets/index-Soe6cpLA.css] ✓ gzip used (32494 -> 5368)
|
|
46
|
+
[favicon.png] x gzip unused (33249 -> 33282)
|
|
47
|
+
[index.html] x gzip unused (too small) (472 -> 308)
|
|
48
|
+
[roboto_regular.json] ✓ gzip used (363757 -> 93567)
|
|
54
49
|
|
|
55
50
|
5 files, 458kB original size, 142kB gzip size
|
|
56
51
|
../../../Arduino/EspSvelte/svelteesp32.h 842kB size
|
|
@@ -107,7 +102,8 @@ The content of **generated file** (do not edit, just use)
|
|
|
107
102
|
```c
|
|
108
103
|
#define SVELTEESP32_COUNT 5
|
|
109
104
|
#define SVELTEESP32_SIZE 145633
|
|
110
|
-
#define
|
|
105
|
+
#define SVELTEESP32_FILE_INDEX_HTML
|
|
106
|
+
#define SVELTEESP32_HTML_FILES 1
|
|
111
107
|
...
|
|
112
108
|
|
|
113
109
|
const uint8_t data0[12547] = {0x1f, 0x8b, 0x8, 0x0, ...
|
|
@@ -157,9 +153,11 @@ If you **only work on ESP32**, I recommend using PsychicHttpServer, which uses t
|
|
|
157
153
|
|
|
158
154
|
All modern browsers have been able to handle gzip-compressed content for years. For this reason, there is no question that the easily compressed JS and CSS files are stored compressed in the ESP32/ESP8266 and sent to the browser.
|
|
159
155
|
|
|
160
|
-
During the translation process, data in gzip format is generated and will be used if the **size is greater than
|
|
156
|
+
During the translation process, data in gzip format is generated and will be used if the **size is greater than 1024 bytes** and we experience a **reduction of at least 15%**. In such a case, the compressed data is unconditionally sent to the browser with the appropriate **Content-Encoding** header information.
|
|
161
157
|
|
|
162
|
-
Automatic compression can be turned off with the `--
|
|
158
|
+
Automatic compression can be turned off with the `--gzip=false` option.
|
|
159
|
+
|
|
160
|
+
> This setting has three states: yes, no, and compiler mode is available. In compiler mode, you can disable/enable Gzip by setting the `SVELTEESP32_ENABLE_GZIP` c++ compiler directive. For example, if using platformio, just write `-D SVELTEESP32_ENABLE_GZIP`.
|
|
163
161
|
|
|
164
162
|
### ETag
|
|
165
163
|
|
|
@@ -167,7 +165,9 @@ The ETag HTTP header can be used to significantly reduce network traffic. If the
|
|
|
167
165
|
|
|
168
166
|
Since microcontroller data traffic is moderately expensive, it is an individual decision whether to use the ETag or not. We **recommend using ETag**, which adds a bit more code (about 1-3%) but results in a much cleaner operation.
|
|
169
167
|
|
|
170
|
-
The use of ETag is **not enabled by default**, this can be achieved with the `--etag` switch.
|
|
168
|
+
The use of ETag is **not enabled by default**, this can be achieved with the `--etag=true` switch.
|
|
169
|
+
|
|
170
|
+
> This setting has three states: yes, no, and compiler mode is available. In compiler mode, you can disable/enable ETag by setting the `SVELTEESP32_ENABLE_ETAG` c++ compiler directive. For example, if using platformio, just type `-D SVELTEESP32_ENABLE_ETAG`.
|
|
171
171
|
|
|
172
172
|
### Main entry point - index.html
|
|
173
173
|
|
|
@@ -189,39 +189,59 @@ You can use the COUNT and SIZE constants:
|
|
|
189
189
|
...
|
|
190
190
|
```
|
|
191
191
|
|
|
192
|
-
You can include a
|
|
192
|
+
You can include a blocker error if a named file accidentally missing from the build:
|
|
193
193
|
|
|
194
194
|
```c
|
|
195
195
|
...
|
|
196
196
|
#include "svelteesp32.h"
|
|
197
197
|
|
|
198
|
-
#ifndef
|
|
198
|
+
#ifndef SVELTEESP32_FILE_INDEX_HTML
|
|
199
199
|
#error Missing index file
|
|
200
200
|
#endif
|
|
201
201
|
...
|
|
202
202
|
```
|
|
203
203
|
|
|
204
|
+
...or if there are too many of a file type:
|
|
205
|
+
|
|
206
|
+
```c
|
|
207
|
+
...
|
|
208
|
+
#include "svelteesp32.h"
|
|
209
|
+
|
|
210
|
+
#if SVELTEESP32_CSS_FILES > 1
|
|
211
|
+
#error Too many CSS files
|
|
212
|
+
#endif
|
|
213
|
+
...
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
You can use the following c++ directives at the project level if you want to configure the usage there: `SVELTEESP32_ENABLE_ETAG` and `SVELTEESP32_ENABLE_GZIP`. (Do not forget `--etag=compiler` or `--gzip=compiler` command line arg!)
|
|
217
|
+
|
|
204
218
|
### Command line options
|
|
205
219
|
|
|
206
|
-
| Option |
|
|
207
|
-
| ------------- |
|
|
208
|
-
| `-
|
|
209
|
-
| `-
|
|
210
|
-
| `-o` |
|
|
211
|
-
| `--etag` |
|
|
212
|
-
| `--
|
|
213
|
-
| `--
|
|
214
|
-
| `--
|
|
215
|
-
|
|
|
220
|
+
| Option | Description | default |
|
|
221
|
+
| ------------- | ---------------------------------------------------------------- | ----------------------- |
|
|
222
|
+
| `-s` | **Source dist folder contains compiled web files** | |
|
|
223
|
+
| `-e` | The engine for which the include file is created (psychic/async) | psychic |
|
|
224
|
+
| `-o` | Generated output file with path | `svelteesp32.h` |
|
|
225
|
+
| `--etag` | Use ETag header for cache (true/false/compiler) | false |
|
|
226
|
+
| `--gzip` | Compress content with gzip (true/false/compiler) | true |
|
|
227
|
+
| `--created` | Include creation time | false |
|
|
228
|
+
| `--version` | Include a version string, `--version=v$npm_package_version` | '' |
|
|
229
|
+
| `--espmethod` | Name of generated method | `initSvelteStaticFiles` |
|
|
230
|
+
| `--define` | Prefix of c++ defines | `SVELTEESP32` |
|
|
231
|
+
| `-h` | Show help | |
|
|
216
232
|
|
|
217
233
|
### Q&A
|
|
218
234
|
|
|
219
235
|
- **How big a frontend application can be placed?** If you compress the content with gzip, even a 3-4Mb assets directory can be placed. This is a serious enough amount to serve a complete application.
|
|
220
236
|
|
|
221
|
-
- **How fast is cpp file compilation?** The cpp file can be large, but it can be compiled in a few seconds on any machine. If you don't modify your svelte/react app, it will use the already compiled cpp file (not recompile). This does not increase the speed of ESP32/ESP8266 development.
|
|
237
|
+
- **How fast is cpp file compilation?** The cpp (.h) file can be large, but it can be compiled in a few seconds on any machine. If you don't modify your svelte/react app, it will use the already compiled cpp file (not recompile). This does not increase the speed of ESP32/ESP8266 development.
|
|
222
238
|
|
|
223
239
|
- **Does the solution use PROGMEM?** No and yes. ESP32 no longer has PROGMEM. (Exists, but does not affect the translation). Instead, if we use a const array in the global namespace, its content will be placed in the code area, i.e. it will not be used from the heap or the stack, so the content of the files to be served will be placed next to the code. When working on ESP8266, PROGMEM will actually be used.
|
|
224
240
|
|
|
225
|
-
- **
|
|
241
|
+
- **Why is the .h file so big?** The source files are always larger than the binary compiled from them. Does the size information in the header (SVELTEESP32_SIZE, SVELTEESP32_SIZE_GZIP) show the actual memory allocation.
|
|
242
|
+
|
|
243
|
+
- **Is collaboration between groups supported?** Yes, the Frontend team produces the application, the use of svelteesp32 is part of the build process. Then, provided with a version number, the .h file is placed in git, which the ESP team translates into the platformio application.
|
|
226
244
|
|
|
227
245
|
- **Will you develop it further?** Since I use it myself, I will do my best to make the solution better and better.
|
|
246
|
+
|
|
247
|
+
- **Is this safe to use in production?** I suggest you give it a try! If you find it useful and safe in several different situations, feel free to use it, just like any other free library.
|
package/dist/commandLine.d.ts
CHANGED
|
@@ -4,8 +4,10 @@ interface ICopyFilesArguments {
|
|
|
4
4
|
outputfile: string;
|
|
5
5
|
espmethod: string;
|
|
6
6
|
define: string;
|
|
7
|
-
|
|
8
|
-
etag:
|
|
7
|
+
gzip: 'true' | 'false' | 'compiler';
|
|
8
|
+
etag: 'true' | 'false' | 'compiler';
|
|
9
|
+
created: boolean;
|
|
10
|
+
version: string;
|
|
9
11
|
help?: boolean;
|
|
10
12
|
}
|
|
11
13
|
export declare const cmdLine: ICopyFilesArguments;
|
package/dist/commandLine.js
CHANGED
|
@@ -13,7 +13,7 @@ exports.cmdLine = (0, ts_command_line_args_1.parse)({
|
|
|
13
13
|
throw new Error(`Invalid engine: ${value}`);
|
|
14
14
|
},
|
|
15
15
|
alias: 'e',
|
|
16
|
-
description: 'The engine for which the include file is created',
|
|
16
|
+
description: 'The engine for which the include file is created (psychic|async)',
|
|
17
17
|
defaultValue: 'psychic'
|
|
18
18
|
},
|
|
19
19
|
sourcepath: {
|
|
@@ -27,16 +27,42 @@ exports.cmdLine = (0, ts_command_line_args_1.parse)({
|
|
|
27
27
|
description: 'Generated output file with path',
|
|
28
28
|
defaultValue: 'svelteesp32.h'
|
|
29
29
|
},
|
|
30
|
-
'no-gzip': {
|
|
31
|
-
type: Boolean,
|
|
32
|
-
description: 'Do not compress content with gzip',
|
|
33
|
-
defaultValue: false
|
|
34
|
-
},
|
|
35
30
|
etag: {
|
|
36
|
-
type:
|
|
31
|
+
type: (value) => {
|
|
32
|
+
if (value === 'true')
|
|
33
|
+
return 'true';
|
|
34
|
+
if (value === 'false')
|
|
35
|
+
return 'false';
|
|
36
|
+
if (value === 'compiler')
|
|
37
|
+
return 'compiler';
|
|
38
|
+
throw new Error(`Invalid etag: ${value}`);
|
|
39
|
+
},
|
|
37
40
|
description: 'Use ETAG header for cache',
|
|
41
|
+
defaultValue: 'false'
|
|
42
|
+
},
|
|
43
|
+
gzip: {
|
|
44
|
+
type: (value) => {
|
|
45
|
+
if (value === 'true')
|
|
46
|
+
return 'true';
|
|
47
|
+
if (value === 'false')
|
|
48
|
+
return 'false';
|
|
49
|
+
if (value === 'compiler')
|
|
50
|
+
return 'compiler';
|
|
51
|
+
throw new Error(`Invalid etag: ${value}`);
|
|
52
|
+
},
|
|
53
|
+
description: 'Compress content with gzip',
|
|
54
|
+
defaultValue: 'true'
|
|
55
|
+
},
|
|
56
|
+
created: {
|
|
57
|
+
type: Boolean,
|
|
58
|
+
description: 'Include creation time in the output file',
|
|
38
59
|
defaultValue: false
|
|
39
60
|
},
|
|
61
|
+
version: {
|
|
62
|
+
type: String,
|
|
63
|
+
description: 'Include version info in the output file',
|
|
64
|
+
defaultValue: ''
|
|
65
|
+
},
|
|
40
66
|
espmethod: {
|
|
41
67
|
type: String,
|
|
42
68
|
description: 'Name of generated method',
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.redLog = exports.yellowLog = exports.greenLog = void 0;
|
|
4
|
+
const greenLog = (s) => `\u001B[32m ${s} \u001B[0m`;
|
|
5
|
+
exports.greenLog = greenLog;
|
|
6
|
+
const yellowLog = (s) => `\u001B[33m ${s} \u001B[0m`;
|
|
7
|
+
exports.yellowLog = yellowLog;
|
|
8
|
+
const redLog = (s) => `\u001B[31m ${s} \u001B[0m`;
|
|
9
|
+
exports.redLog = redLog;
|
package/dist/cppCode.d.ts
CHANGED
|
@@ -1,9 +1,17 @@
|
|
|
1
|
-
export type
|
|
1
|
+
export type CppCodeSource = {
|
|
2
2
|
filename: string;
|
|
3
3
|
dataname: string;
|
|
4
|
+
datanameUpperCase: string;
|
|
4
5
|
mime: string;
|
|
5
6
|
content: Buffer;
|
|
7
|
+
contentGzip: Buffer;
|
|
6
8
|
isGzip: boolean;
|
|
7
9
|
md5: string;
|
|
8
10
|
};
|
|
9
|
-
export
|
|
11
|
+
export type CppCodeSources = CppCodeSource[];
|
|
12
|
+
export type ExtensionGroup = {
|
|
13
|
+
extension: string;
|
|
14
|
+
count: number;
|
|
15
|
+
};
|
|
16
|
+
export type ExtensionGroups = ExtensionGroup[];
|
|
17
|
+
export declare const getCppCode: (sources: CppCodeSources, filesByExtension: ExtensionGroups) => string;
|
package/dist/cppCode.js
CHANGED
|
@@ -5,47 +5,176 @@ const handlebars_1 = require("handlebars");
|
|
|
5
5
|
const commandLine_1 = require("./commandLine");
|
|
6
6
|
const psychicTemplate = `
|
|
7
7
|
//engine: PsychicHttpServer
|
|
8
|
-
//cmdline: {{commandLine}}
|
|
8
|
+
//cmdline: {{{commandLine}}}
|
|
9
|
+
{{#if created }}
|
|
9
10
|
//created: {{now}}
|
|
10
|
-
|
|
11
|
-
//
|
|
11
|
+
{{/if}}
|
|
12
|
+
//
|
|
12
13
|
|
|
13
|
-
#
|
|
14
|
-
#
|
|
15
|
-
#
|
|
14
|
+
{{#switch etag}}
|
|
15
|
+
{{#case "true"}}
|
|
16
|
+
#ifdef {{definePrefix}}_ENABLE_ETAG
|
|
17
|
+
#warning {{definePrefix}}_ENABLE_ETAG has no effect because it is permanently switched ON
|
|
18
|
+
#endif
|
|
19
|
+
{{/case}}
|
|
20
|
+
{{#case "false"}}
|
|
21
|
+
#ifdef {{definePrefix}}_ENABLE_ETAG
|
|
22
|
+
#warning {{definePrefix}}_ENABLE_ETAG has no effect because it is permanently switched OFF
|
|
23
|
+
#endif
|
|
24
|
+
{{/case}}
|
|
25
|
+
{{/switch}}
|
|
26
|
+
|
|
27
|
+
{{#switch gzip}}
|
|
28
|
+
{{#case "true"}}
|
|
29
|
+
#ifdef {{definePrefix}}_ENABLE_GZIP
|
|
30
|
+
#warning {{definePrefix}}_ENABLE_GZIP has no effect because it is permanently switched ON
|
|
31
|
+
#endif
|
|
32
|
+
{{/case}}
|
|
33
|
+
{{#case "false"}}
|
|
34
|
+
#ifdef {{definePrefix}}_ENABLE_GZIP
|
|
35
|
+
#warning {{definePrefix}}_ENABLE_GZIP has no effect because it is permanently switched OFF
|
|
36
|
+
#endif
|
|
37
|
+
{{/case}}
|
|
38
|
+
{{/switch}}
|
|
16
39
|
|
|
40
|
+
//
|
|
41
|
+
{{#if version }}
|
|
42
|
+
#define {{definePrefix}}_VERSION "{{version}}"
|
|
43
|
+
{{/if}}
|
|
17
44
|
#define {{definePrefix}}_COUNT {{fileCount}}
|
|
18
45
|
#define {{definePrefix}}_SIZE {{fileSize}}
|
|
46
|
+
#define {{definePrefix}}_SIZE_GZIP {{fileGzipSize}}
|
|
47
|
+
|
|
48
|
+
//
|
|
19
49
|
{{#each sources}}
|
|
20
|
-
#define {{../definePrefix}}_FILE_{{this.
|
|
50
|
+
#define {{../definePrefix}}_FILE_{{this.datanameUpperCase}}
|
|
21
51
|
{{/each}}
|
|
22
52
|
|
|
23
|
-
|
|
53
|
+
//
|
|
54
|
+
{{#each filesByExtension}}
|
|
55
|
+
#define {{../definePrefix}}_{{this.extension}}_FILES {{this.count}}
|
|
56
|
+
{{/each}}
|
|
57
|
+
|
|
58
|
+
//
|
|
59
|
+
#include <Arduino.h>
|
|
60
|
+
#include <PsychicHttp.h>
|
|
61
|
+
#include <PsychicHttpsServer.h>
|
|
62
|
+
|
|
63
|
+
//
|
|
64
|
+
{{#switch gzip}}
|
|
65
|
+
{{#case "true"}}
|
|
66
|
+
{{#each sources}}
|
|
67
|
+
const uint8_t datagzip_{{this.dataname}}[{{this.lengthGzip}}] = { {{this.bytesGzip}} };
|
|
68
|
+
{{/each}}
|
|
69
|
+
{{/case}}
|
|
70
|
+
{{#case "false"}}
|
|
71
|
+
{{#each sources}}
|
|
24
72
|
const uint8_t data_{{this.dataname}}[{{this.length}}] = { {{this.bytes}} };
|
|
25
|
-
{{
|
|
73
|
+
{{/each}}
|
|
74
|
+
{{/case}}
|
|
75
|
+
{{#case "compiler"}}
|
|
76
|
+
#ifdef {{definePrefix}}_ENABLE_GZIP
|
|
77
|
+
{{#each sources}}
|
|
78
|
+
const uint8_t datagzip_{{this.dataname}}[{{this.lengthGzip}}] = { {{this.bytesGzip}} };
|
|
79
|
+
{{/each}}
|
|
80
|
+
#else
|
|
81
|
+
{{#each sources}}
|
|
82
|
+
const uint8_t data_{{this.dataname}}[{{this.length}}] = { {{this.bytes}} };
|
|
83
|
+
{{/each}}
|
|
84
|
+
#endif
|
|
85
|
+
{{/case}}
|
|
86
|
+
{{/switch}}
|
|
87
|
+
|
|
88
|
+
//
|
|
89
|
+
{{#switch etag}}
|
|
90
|
+
{{#case "true"}}
|
|
91
|
+
{{#each sources}}
|
|
26
92
|
const char * etag_{{this.dataname}} = "{{this.md5}}";
|
|
27
|
-
{{/
|
|
28
|
-
{{/
|
|
93
|
+
{{/each}}
|
|
94
|
+
{{/case}}
|
|
95
|
+
{{#case "false"}}
|
|
96
|
+
{{/case}}
|
|
97
|
+
{{#case "compiler"}}
|
|
98
|
+
#ifdef {{definePrefix}}_ENABLE_ETAG
|
|
99
|
+
{{#each sources}}
|
|
100
|
+
const char * etag_{{this.dataname}} = "{{this.md5}}";
|
|
101
|
+
{{/each}}
|
|
102
|
+
#endif
|
|
103
|
+
{{/case}}
|
|
104
|
+
{{/switch}}
|
|
29
105
|
|
|
106
|
+
//
|
|
107
|
+
// Http Handlers
|
|
30
108
|
void {{methodName}}(PsychicHttpServer * server) {
|
|
31
109
|
{{#each sources}}
|
|
110
|
+
//
|
|
111
|
+
// {{this.filename}}
|
|
32
112
|
{{#if this.isDefault}}server->defaultEndpoint = {{/if}}server->on("/{{this.filename}}", HTTP_GET, [](PsychicRequest * request) {
|
|
33
|
-
|
|
113
|
+
|
|
114
|
+
{{#switch ../etag}}
|
|
115
|
+
{{#case "true"}}
|
|
34
116
|
if (request->hasHeader("If-None-Match") && request->header("If-None-Match") == String(etag_{{this.dataname}})) {
|
|
35
117
|
PsychicResponse response304(request);
|
|
36
118
|
response304.setCode(304);
|
|
37
119
|
return response304.send();
|
|
38
120
|
}
|
|
39
|
-
|
|
121
|
+
{{/case}}
|
|
122
|
+
{{#case "compiler"}}
|
|
123
|
+
#ifdef {{../definePrefix}}_ENABLE_ETAG
|
|
124
|
+
if (request->hasHeader("If-None-Match") && request->header("If-None-Match") == String(etag_{{this.dataname}})) {
|
|
125
|
+
PsychicResponse response304(request);
|
|
126
|
+
response304.setCode(304);
|
|
127
|
+
return response304.send();
|
|
128
|
+
}
|
|
129
|
+
#endif
|
|
130
|
+
{{/case}}
|
|
131
|
+
{{/switch}}
|
|
132
|
+
|
|
40
133
|
PsychicResponse response(request);
|
|
41
134
|
response.setContentType("{{this.mime}}");
|
|
42
|
-
|
|
135
|
+
|
|
136
|
+
{{#switch ../gzip}}
|
|
137
|
+
{{#case "true"}}
|
|
138
|
+
{{#if this.isGzip}}
|
|
43
139
|
response.addHeader("Content-Encoding", "gzip");
|
|
44
|
-
|
|
45
|
-
|
|
140
|
+
{{/if}}
|
|
141
|
+
{{/case}}
|
|
142
|
+
{{#case "compiler"}}
|
|
143
|
+
{{#if this.isGzip}}
|
|
144
|
+
#ifdef {{../definePrefix}}_ENABLE_GZIP
|
|
145
|
+
response.addHeader("Content-Encoding", "gzip");
|
|
146
|
+
#endif
|
|
147
|
+
{{/if}}
|
|
148
|
+
{{/case}}
|
|
149
|
+
{{/switch}}
|
|
150
|
+
|
|
151
|
+
{{#switch ../etag}}
|
|
152
|
+
{{#case "true"}}
|
|
46
153
|
response.addHeader("ETag", etag_{{this.dataname}});
|
|
47
|
-
|
|
48
|
-
|
|
154
|
+
{{/case}}
|
|
155
|
+
{{#case "compiler"}}
|
|
156
|
+
#ifdef {{../definePrefix}}_ENABLE_ETAG
|
|
157
|
+
response.addHeader("ETag", etag_{{this.dataname}});
|
|
158
|
+
#endif
|
|
159
|
+
{{/case}}
|
|
160
|
+
{{/switch}}
|
|
161
|
+
|
|
162
|
+
{{#switch ../gzip}}
|
|
163
|
+
{{#case "true"}}
|
|
164
|
+
response.setContent(datagzip_{{this.dataname}}, {{this.lengthGzip}});
|
|
165
|
+
{{/case}}
|
|
166
|
+
{{#case "false"}}
|
|
167
|
+
response.setContent(data_{{this.dataname}}, {{this.length}});
|
|
168
|
+
{{/case}}
|
|
169
|
+
{{#case "compiler"}}
|
|
170
|
+
#ifdef {{../definePrefix}}_ENABLE_GZIP
|
|
171
|
+
response.setContent(datagzip_{{this.dataname}}, {{this.lengthGzip}});
|
|
172
|
+
#else
|
|
173
|
+
response.setContent(data_{{this.dataname}}, {{this.length}});
|
|
174
|
+
#endif
|
|
175
|
+
{{/case}}
|
|
176
|
+
{{/switch}}
|
|
177
|
+
|
|
49
178
|
return response.send();
|
|
50
179
|
});
|
|
51
180
|
|
|
@@ -53,43 +182,161 @@ void {{methodName}}(PsychicHttpServer * server) {
|
|
|
53
182
|
}`;
|
|
54
183
|
const asyncTemplate = `
|
|
55
184
|
//engine: ESPAsyncWebServer
|
|
56
|
-
//cmdline: {{commandLine}}
|
|
185
|
+
//cmdline: {{{commandLine}}}
|
|
186
|
+
{{#if created }}
|
|
57
187
|
//created: {{now}}
|
|
58
|
-
|
|
59
|
-
//
|
|
188
|
+
{{/if}}
|
|
189
|
+
//
|
|
60
190
|
|
|
61
|
-
#
|
|
62
|
-
#
|
|
191
|
+
{{#switch etag}}
|
|
192
|
+
{{#case "true"}}
|
|
193
|
+
#ifdef {{definePrefix}}_ENABLE_ETAG
|
|
194
|
+
#warning {{definePrefix}}_ENABLE_ETAG has no effect because it is permanently switched ON
|
|
195
|
+
#endif
|
|
196
|
+
{{/case}}
|
|
197
|
+
{{#case "false"}}
|
|
198
|
+
#ifdef {{definePrefix}}_ENABLE_ETAG
|
|
199
|
+
#warning {{definePrefix}}_ENABLE_ETAG has no effect because it is permanently switched OFF
|
|
200
|
+
#endif
|
|
201
|
+
{{/case}}
|
|
202
|
+
{{/switch}}
|
|
203
|
+
|
|
204
|
+
{{#switch gzip}}
|
|
205
|
+
{{#case "true"}}
|
|
206
|
+
#ifdef {{definePrefix}}_ENABLE_GZIP
|
|
207
|
+
#warning {{definePrefix}}_ENABLE_GZIP has no effect because it is permanently switched ON
|
|
208
|
+
#endif
|
|
209
|
+
{{/case}}
|
|
210
|
+
{{#case "false"}}
|
|
211
|
+
#ifdef {{definePrefix}}_ENABLE_GZIP
|
|
212
|
+
#warning {{definePrefix}}_ENABLE_GZIP has no effect because it is permanently switched OFF
|
|
213
|
+
#endif
|
|
214
|
+
{{/case}}
|
|
215
|
+
{{/switch}}
|
|
63
216
|
|
|
217
|
+
//
|
|
218
|
+
{{#if version }}
|
|
219
|
+
#define {{definePrefix}}_VERSION "{{version}}"
|
|
220
|
+
{{/if}}
|
|
64
221
|
#define {{definePrefix}}_COUNT {{fileCount}}
|
|
65
222
|
#define {{definePrefix}}_SIZE {{fileSize}}
|
|
223
|
+
#define {{definePrefix}}_SIZE_GZIP {{fileGzipSize}}
|
|
224
|
+
|
|
225
|
+
//
|
|
66
226
|
{{#each sources}}
|
|
67
|
-
#define {{../definePrefix}}_FILE_{{this.
|
|
227
|
+
#define {{../definePrefix}}_FILE_{{this.datanameUpperCase}}
|
|
68
228
|
{{/each}}
|
|
69
229
|
|
|
70
|
-
|
|
230
|
+
//
|
|
231
|
+
{{#each filesByExtension}}
|
|
232
|
+
#define {{../definePrefix}}_{{this.extension}}_FILES {{this.count}}
|
|
233
|
+
{{/each}}
|
|
234
|
+
|
|
235
|
+
//
|
|
236
|
+
#include <Arduino.h>
|
|
237
|
+
#include <ESPAsyncWebServer.h>
|
|
238
|
+
|
|
239
|
+
//
|
|
240
|
+
{{#switch gzip}}
|
|
241
|
+
{{#case "true"}}
|
|
242
|
+
{{#each sources}}
|
|
243
|
+
const uint8_t datagzip_{{this.dataname}}[{{this.lengthGzip}}] PROGMEM = { {{this.bytesGzip}} };
|
|
244
|
+
{{/each}}
|
|
245
|
+
{{/case}}
|
|
246
|
+
{{#case "false"}}
|
|
247
|
+
{{#each sources}}
|
|
71
248
|
const uint8_t data_{{this.dataname}}[{{this.length}}] PROGMEM = { {{this.bytes}} };
|
|
72
|
-
{{
|
|
249
|
+
{{/each}}
|
|
250
|
+
{{/case}}
|
|
251
|
+
{{#case "compiler"}}
|
|
252
|
+
#ifdef {{definePrefix}}_ENABLE_GZIP
|
|
253
|
+
{{#each sources}}
|
|
254
|
+
const uint8_t datagzip_{{this.dataname}}[{{this.lengthGzip}}] PROGMEM = { {{this.bytesGzip}} };
|
|
255
|
+
{{/each}}
|
|
256
|
+
#else
|
|
257
|
+
{{#each sources}}
|
|
258
|
+
const uint8_t data_{{this.dataname}}[{{this.length}}] PROGMEM = { {{this.bytes}} };
|
|
259
|
+
{{/each}}
|
|
260
|
+
#endif
|
|
261
|
+
{{/case}}
|
|
262
|
+
{{/switch}}
|
|
263
|
+
|
|
264
|
+
//
|
|
265
|
+
{{#switch etag}}
|
|
266
|
+
{{#case "true"}}
|
|
267
|
+
{{#each sources}}
|
|
73
268
|
const char * etag_{{this.dataname}} = "{{this.md5}}";
|
|
74
|
-
{{/
|
|
75
|
-
{{/
|
|
269
|
+
{{/each}}
|
|
270
|
+
{{/case}}
|
|
271
|
+
{{#case "false"}}
|
|
272
|
+
{{/case}}
|
|
273
|
+
{{#case "compiler"}}
|
|
274
|
+
#ifdef {{definePrefix}}_ENABLE_ETAG
|
|
275
|
+
{{#each sources}}
|
|
276
|
+
const char * etag_{{this.dataname}} = "{{this.md5}}";
|
|
277
|
+
{{/each}}
|
|
278
|
+
#endif
|
|
279
|
+
{{/case}}
|
|
280
|
+
{{/switch}}
|
|
76
281
|
|
|
282
|
+
//
|
|
283
|
+
// Http Handlers
|
|
77
284
|
void {{methodName}}(AsyncWebServer * server) {
|
|
78
285
|
{{#each sources}}
|
|
286
|
+
//
|
|
287
|
+
// {{this.filename}}
|
|
79
288
|
ArRequestHandlerFunction func_{{this.dataname}} = [](AsyncWebServerRequest * request) {
|
|
80
|
-
|
|
289
|
+
|
|
290
|
+
{{#switch ../etag}}
|
|
291
|
+
{{#case "true"}}
|
|
81
292
|
if (request->hasHeader("If-None-Match") && request->getHeader("If-None-Match")->value() == String(etag_{{this.dataname}})) {
|
|
82
293
|
request->send(304);
|
|
83
294
|
return;
|
|
84
295
|
}
|
|
296
|
+
{{/case}}
|
|
297
|
+
{{#case "compiler"}}
|
|
298
|
+
#ifdef {{../definePrefix}}_ENABLE_ETAG
|
|
299
|
+
if (request->hasHeader("If-None-Match") && request->getHeader("If-None-Match")->value() == String(etag_{{this.dataname}})) {
|
|
300
|
+
request->send(304);
|
|
301
|
+
return;
|
|
302
|
+
}
|
|
303
|
+
#endif
|
|
304
|
+
{{/case}}
|
|
305
|
+
{{/switch}}
|
|
306
|
+
|
|
307
|
+
{{#switch ../gzip}}
|
|
308
|
+
{{#case "true"}}
|
|
309
|
+
AsyncWebServerResponse *response = request->beginResponse_P(200, "{{this.mime}}", datagzip_{{this.dataname}}, {{this.lengthGzip}});
|
|
310
|
+
{{#if this.isGzip}}
|
|
311
|
+
response->addHeader("Content-Encoding", "gzip");
|
|
85
312
|
{{/if}}
|
|
313
|
+
{{/case}}
|
|
314
|
+
{{#case "false"}}
|
|
86
315
|
AsyncWebServerResponse *response = request->beginResponse_P(200, "{{this.mime}}", data_{{this.dataname}}, {{this.length}});
|
|
316
|
+
{{/case}}
|
|
317
|
+
{{#case "compiler"}}
|
|
318
|
+
#ifdef {{../definePrefix}}_ENABLE_GZIP
|
|
319
|
+
AsyncWebServerResponse *response = request->beginResponse_P(200, "{{this.mime}}", datagzip_{{this.dataname}}, {{this.lengthGzip}});
|
|
87
320
|
{{#if this.isGzip}}
|
|
88
321
|
response->addHeader("Content-Encoding", "gzip");
|
|
89
322
|
{{/if}}
|
|
90
|
-
|
|
323
|
+
#else
|
|
324
|
+
AsyncWebServerResponse *response = request->beginResponse_P(200, "{{this.mime}}", data_{{this.dataname}}, {{this.length}});
|
|
325
|
+
#endif
|
|
326
|
+
{{/case}}
|
|
327
|
+
{{/switch}}
|
|
328
|
+
|
|
329
|
+
{{#switch ../etag}}
|
|
330
|
+
{{#case "true"}}
|
|
91
331
|
response->addHeader("ETag", etag_{{this.dataname}});
|
|
92
|
-
|
|
332
|
+
{{/case}}
|
|
333
|
+
{{#case "compiler"}}
|
|
334
|
+
#ifdef {{../definePrefix}}_ENABLE_ETAG
|
|
335
|
+
response->addHeader("ETag", etag_{{this.dataname}});
|
|
336
|
+
#endif
|
|
337
|
+
{{/case}}
|
|
338
|
+
{{/switch}}
|
|
339
|
+
|
|
93
340
|
request->send(response);
|
|
94
341
|
};
|
|
95
342
|
server->on("/{{this.filename}}", HTTP_GET, func_{{this.dataname}});
|
|
@@ -99,19 +346,50 @@ void {{methodName}}(AsyncWebServer * server) {
|
|
|
99
346
|
|
|
100
347
|
{{/each}}
|
|
101
348
|
}`;
|
|
102
|
-
|
|
349
|
+
let switchValue;
|
|
350
|
+
const getCppCode = (sources, filesByExtension) => (0, handlebars_1.compile)(commandLine_1.cmdLine.engine === 'psychic' ? psychicTemplate : asyncTemplate)({
|
|
103
351
|
commandLine: process.argv.slice(2).join(' '),
|
|
104
352
|
now: `${new Date().toLocaleDateString()} ${new Date().toLocaleTimeString()}`,
|
|
105
353
|
fileCount: sources.length.toString(),
|
|
106
354
|
fileSize: sources.reduce((previous, current) => previous + current.content.length, 0).toString(),
|
|
355
|
+
fileGzipSize: sources.reduce((previous, current) => previous + current.contentGzip.length, 0).toString(),
|
|
107
356
|
sources: sources.map((s) => ({
|
|
108
357
|
...s,
|
|
109
358
|
length: s.content.length,
|
|
110
|
-
bytes: [...s.content].map((v) =>
|
|
359
|
+
bytes: [...s.content].map((v) => `${v.toString(10)}`).join(','),
|
|
360
|
+
lengthGzip: s.contentGzip.length,
|
|
361
|
+
bytesGzip: [...s.contentGzip].map((v) => `${v.toString(10)}`).join(','),
|
|
111
362
|
isDefault: s.filename.startsWith('index.htm')
|
|
112
363
|
})),
|
|
113
|
-
|
|
364
|
+
filesByExtension,
|
|
365
|
+
etag: commandLine_1.cmdLine.etag,
|
|
366
|
+
gzip: commandLine_1.cmdLine.gzip,
|
|
367
|
+
created: commandLine_1.cmdLine.created,
|
|
368
|
+
version: commandLine_1.cmdLine.version,
|
|
114
369
|
methodName: commandLine_1.cmdLine.espmethod,
|
|
115
370
|
definePrefix: commandLine_1.cmdLine.define
|
|
116
|
-
}
|
|
371
|
+
}, {
|
|
372
|
+
helpers: {
|
|
373
|
+
ifeq: function (a, b, options) {
|
|
374
|
+
if (a == b)
|
|
375
|
+
return options.fn(this);
|
|
376
|
+
return options.inverse(this);
|
|
377
|
+
},
|
|
378
|
+
switch: function (value, options) {
|
|
379
|
+
switchValue = value;
|
|
380
|
+
return options.fn(this);
|
|
381
|
+
},
|
|
382
|
+
case: function (value, options) {
|
|
383
|
+
if (value == switchValue)
|
|
384
|
+
return options.fn(this);
|
|
385
|
+
return options.inverse(this);
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
})
|
|
389
|
+
.split('\n')
|
|
390
|
+
.map((line) => line.trimEnd())
|
|
391
|
+
.filter(Boolean)
|
|
392
|
+
.map((line) => (line == '//' ? '' : line))
|
|
393
|
+
.join('\n')
|
|
394
|
+
.replace(/\\n{2}/, '\n');
|
|
117
395
|
exports.getCppCode = getCppCode;
|
package/dist/file.js
CHANGED
|
@@ -7,7 +7,20 @@ exports.getFiles = void 0;
|
|
|
7
7
|
const node_path_1 = __importDefault(require("node:path"));
|
|
8
8
|
const glob_1 = require("glob");
|
|
9
9
|
const commandLine_1 = require("./commandLine");
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
.
|
|
10
|
+
const consoleColor_1 = require("./consoleColor");
|
|
11
|
+
const getFiles = () => {
|
|
12
|
+
let files = (0, glob_1.globSync)('**/*', { cwd: commandLine_1.cmdLine.sourcepath, nodir: true });
|
|
13
|
+
files = files.filter((filename) => {
|
|
14
|
+
const extension = node_path_1.default.extname(filename);
|
|
15
|
+
if (['.gz', '.brottli', '.br'].includes(extension)) {
|
|
16
|
+
const original = filename.slice(0, -1 * extension.length);
|
|
17
|
+
if (files.includes(original)) {
|
|
18
|
+
console.log((0, consoleColor_1.redLog)(`${filename} skipped because is perhaps a compressed version of ${original}`));
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return true;
|
|
23
|
+
});
|
|
24
|
+
return files.sort();
|
|
25
|
+
};
|
|
13
26
|
exports.getFiles = getFiles;
|
package/dist/index.js
CHANGED
|
@@ -9,6 +9,7 @@ const node_path_1 = __importDefault(require("node:path"));
|
|
|
9
9
|
const node_zlib_1 = require("node:zlib");
|
|
10
10
|
const mime_types_1 = require("mime-types");
|
|
11
11
|
const commandLine_1 = require("./commandLine");
|
|
12
|
+
const consoleColor_1 = require("./consoleColor");
|
|
12
13
|
const cppCode_1 = require("./cppCode");
|
|
13
14
|
const file_1 = require("./file");
|
|
14
15
|
const summary = {
|
|
@@ -17,65 +18,63 @@ const summary = {
|
|
|
17
18
|
gzipsize: 0
|
|
18
19
|
};
|
|
19
20
|
const sources = [];
|
|
21
|
+
const filesByExtension = [];
|
|
20
22
|
const files = (0, file_1.getFiles)();
|
|
21
23
|
if (files.length === 0) {
|
|
22
24
|
console.error(`Directory ${commandLine_1.cmdLine.sourcepath} is empty`);
|
|
23
25
|
process.exit(1);
|
|
24
26
|
}
|
|
27
|
+
const rightPad = files.reduce((p, c) => (c.length > p ? c.length : p), 0);
|
|
25
28
|
for (const file of files) {
|
|
26
29
|
const mime = (0, mime_types_1.lookup)(file) || 'text/plain';
|
|
27
30
|
summary.filecount++;
|
|
28
|
-
console.log(`[${file}]`);
|
|
29
31
|
const filename = file.replace(/\\/g, '/');
|
|
30
32
|
const dataname = filename.replace(/[./-]/g, '_');
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
33
|
+
let extension = node_path_1.default.extname(filename).toUpperCase();
|
|
34
|
+
if (extension.startsWith('.'))
|
|
35
|
+
extension = extension.slice(1);
|
|
36
|
+
const group = filesByExtension.find((fe) => fe.extension === extension);
|
|
37
|
+
if (group)
|
|
38
|
+
group.count += 1;
|
|
39
|
+
else
|
|
40
|
+
filesByExtension.push({ extension, count: 1 });
|
|
41
|
+
const content = (0, node_fs_1.readFileSync)(node_path_1.default.join(commandLine_1.cmdLine.sourcepath, file), { flag: 'r' });
|
|
42
|
+
const md5 = (0, node_crypto_1.createHash)('md5').update(content).digest('hex');
|
|
43
|
+
summary.size += content.length;
|
|
44
|
+
const zipContent = (0, node_zlib_1.gzipSync)(content, { level: 9 });
|
|
45
|
+
summary.gzipsize += zipContent.length;
|
|
46
|
+
const zipRatio = Math.round((zipContent.length / content.length) * 100);
|
|
47
|
+
if (content.length > 1024 && zipContent.length < content.length * 0.85) {
|
|
35
48
|
sources.push({
|
|
36
|
-
filename
|
|
49
|
+
filename,
|
|
37
50
|
dataname,
|
|
38
|
-
|
|
39
|
-
|
|
51
|
+
datanameUpperCase: dataname.toUpperCase(),
|
|
52
|
+
content,
|
|
53
|
+
contentGzip: zipContent,
|
|
54
|
+
isGzip: true,
|
|
40
55
|
mime,
|
|
41
56
|
md5
|
|
42
57
|
});
|
|
43
|
-
console.log(
|
|
58
|
+
console.log((0, consoleColor_1.greenLog)(`[${file}] ${' '.repeat(rightPad - file.length)} ✓ gzip used (${content.length} -> ${zipContent.length} = ${zipRatio}%)`));
|
|
44
59
|
}
|
|
45
60
|
else {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
console.log(`✓ gzip used (${rawContent.length} -> ${zipContent.length})`);
|
|
58
|
-
}
|
|
59
|
-
else {
|
|
60
|
-
sources.push({
|
|
61
|
-
filename: filename,
|
|
62
|
-
dataname,
|
|
63
|
-
content: rawContent,
|
|
64
|
-
isGzip: false,
|
|
65
|
-
mime,
|
|
66
|
-
md5
|
|
67
|
-
});
|
|
68
|
-
console.log(`x gzip unused (${rawContent.length} -> ${zipContent.length})`);
|
|
69
|
-
}
|
|
61
|
+
sources.push({
|
|
62
|
+
filename,
|
|
63
|
+
dataname,
|
|
64
|
+
datanameUpperCase: dataname.toUpperCase(),
|
|
65
|
+
content,
|
|
66
|
+
contentGzip: content,
|
|
67
|
+
isGzip: false,
|
|
68
|
+
mime,
|
|
69
|
+
md5
|
|
70
|
+
});
|
|
71
|
+
console.log((0, consoleColor_1.yellowLog)(`[${file}] ${' '.repeat(rightPad - file.length)} x gzip unused ${content.length <= 1024 ? `(too small) ` : ''}(${content.length} -> ${zipContent.length} = ${zipRatio}%)`));
|
|
70
72
|
}
|
|
71
|
-
console.log('');
|
|
72
|
-
}
|
|
73
|
-
const cppFile = (0, cppCode_1.getCppCode)(sources);
|
|
74
|
-
(0, node_fs_1.writeFileSync)(commandLine_1.cmdLine.outputfile, cppFile);
|
|
75
|
-
if (commandLine_1.cmdLine['no-gzip']) {
|
|
76
|
-
console.log(`${summary.filecount} files, ${Math.round(summary.size / 1024)}kB original size`);
|
|
77
|
-
}
|
|
78
|
-
else {
|
|
79
|
-
console.log(`${summary.filecount} files, ${Math.round(summary.size / 1024)}kB original size, ${Math.round(summary.gzipsize / 1024)}kB gzip size`);
|
|
80
73
|
}
|
|
74
|
+
console.log('');
|
|
75
|
+
filesByExtension.sort((left, right) => left.extension.localeCompare(right.extension));
|
|
76
|
+
const cppFile = (0, cppCode_1.getCppCode)(sources, filesByExtension);
|
|
77
|
+
(0, node_fs_1.mkdirSync)(node_path_1.default.normalize(node_path_1.default.dirname(commandLine_1.cmdLine.outputfile)), { recursive: true });
|
|
78
|
+
(0, node_fs_1.writeFileSync)(commandLine_1.cmdLine.outputfile, cppFile, { flush: true, encoding: 'utf8' });
|
|
79
|
+
console.log(`${summary.filecount} files, ${Math.round(summary.size / 1024)}kB original size, ${Math.round(summary.gzipsize / 1024)}kB gzip size`);
|
|
81
80
|
console.log(`${commandLine_1.cmdLine.outputfile} ${Math.round(cppFile.length / 1024)}kB size`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "svelteesp32",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.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",
|
|
@@ -28,13 +28,9 @@
|
|
|
28
28
|
},
|
|
29
29
|
"homepage": "https://github.com/BCsabaEngine/svelteesp32",
|
|
30
30
|
"scripts": {
|
|
31
|
-
"dev:async": "nodemon src/index.ts -- -e async -s ./demo/svelte/dist -o ./demo/esp32/include/
|
|
32
|
-
"dev:psychic": "nodemon src/index.ts -- -e psychic -s ./demo/svelte/dist -o ./demo/esp32/include/
|
|
33
|
-
"
|
|
34
|
-
"run:psychic": "tsx src/index.ts -e psychic -s ./demo/svelte/dist -o ./demo/esp32/include/svelteesp32psychic.h --etag",
|
|
35
|
-
"run:both": "npm run run:async && npm run run:psychic",
|
|
36
|
-
"platformio": "~/.platformio/penv/bin/pio run -d ./demo/esp32",
|
|
37
|
-
"run:both:build": "npm run run:both && npm run platformio",
|
|
31
|
+
"dev:async": "nodemon src/index.ts -- -e async -s ./demo/svelte/dist -o ./demo/esp32/include/svelteesp32.h --etag=true --gzip=true --version=v$npm_package_version",
|
|
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
|
+
"test:all": "./package.script && ~/.platformio/penv/bin/pio run -d ./demo/esp32",
|
|
38
34
|
"clean": "tsc --build --clean",
|
|
39
35
|
"build": "tsc --build --clean && tsc --build --force",
|
|
40
36
|
"format:check": "prettier --check .",
|
|
@@ -56,7 +52,7 @@
|
|
|
56
52
|
],
|
|
57
53
|
"devDependencies": {
|
|
58
54
|
"@types/mime-types": "^2.1.4",
|
|
59
|
-
"@types/node": "^22.
|
|
55
|
+
"@types/node": "^22.4.0",
|
|
60
56
|
"@typescript-eslint/eslint-plugin": "^8.1.0",
|
|
61
57
|
"@typescript-eslint/parser": "^8.1.0",
|
|
62
58
|
"eslint": "^9.9.0",
|