cc4-embedded-system 3.1.1 → 3.1.2
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/dist/gui.js +1 -1
- package/package.json +7 -2
- package/Screenshot/v3.1.1.png +0 -0
- package/src/gui.ts +0 -227
- package/src/makefsdata.ts +0 -390
- package/src/utils.ts +0 -76
- package/tsconfig.json +0 -29
- /package/{public → dist/public}/index.html +0 -0
package/dist/gui.js
CHANGED
|
@@ -85,7 +85,7 @@ if (portArgIndex !== -1 && process.argv[portArgIndex + 1]) {
|
|
|
85
85
|
let server;
|
|
86
86
|
let shutdownTimer = null;
|
|
87
87
|
app.use(express.json());
|
|
88
|
-
app.use(express.static(path.join(__dirname, '
|
|
88
|
+
app.use(express.static(path.join(__dirname, '/public')));
|
|
89
89
|
const cancelShutdown = () => {
|
|
90
90
|
if (shutdownTimer) {
|
|
91
91
|
clearTimeout(shutdownTimer);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cc4-embedded-system",
|
|
3
|
-
"version": "3.1.
|
|
3
|
+
"version": "3.1.2",
|
|
4
4
|
"description": "A modern typescript version of makefsdata based on html-minifier-next and lwIP v1.3.1",
|
|
5
5
|
"bin": {
|
|
6
6
|
"cc4es": "./dist/gui.js"
|
|
@@ -8,9 +8,14 @@
|
|
|
8
8
|
"type": "module",
|
|
9
9
|
"scripts": {
|
|
10
10
|
"dev": "tsx src/gui.ts",
|
|
11
|
-
"build": "tsc",
|
|
11
|
+
"build": "tsc && xcopy /E /I /Y public dist\\public",
|
|
12
12
|
"prepublishOnly": "npm run build"
|
|
13
13
|
},
|
|
14
|
+
"files": [
|
|
15
|
+
"dist/",
|
|
16
|
+
"package.json",
|
|
17
|
+
"README.md"
|
|
18
|
+
],
|
|
14
19
|
"keywords": [
|
|
15
20
|
"lwip",
|
|
16
21
|
"makefsdata",
|
package/Screenshot/v3.1.1.png
DELETED
|
Binary file
|
package/src/gui.ts
DELETED
|
@@ -1,227 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/*
|
|
4
|
-
* ==============================================================================
|
|
5
|
-
* CC4EmbeddedSystem V3 (makefsdata)
|
|
6
|
-
* Copyright (c) 2026 LunaticGhoulPiano / Emile Su
|
|
7
|
-
* Licensed under the MIT License.
|
|
8
|
-
* ==============================================================================
|
|
9
|
-
*
|
|
10
|
-
* This software integrates concepts, logic, and minification processes derived
|
|
11
|
-
* from the following open-source projects. We deeply appreciate their work:
|
|
12
|
-
*
|
|
13
|
-
* ------------------------------------------------------------------------------
|
|
14
|
-
* 1. lwIP (Lightweight TCP/IP stack)
|
|
15
|
-
* Repository: https://github.com/m-labs/lwip
|
|
16
|
-
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
|
17
|
-
* All rights reserved.
|
|
18
|
-
* * Redistribution and use in source and binary forms, with or without modification,
|
|
19
|
-
* are permitted provided that the following conditions are met:
|
|
20
|
-
* * 1. Redistributions of source code must retain the above copyright notice,
|
|
21
|
-
* this list of conditions and the following disclaimer.
|
|
22
|
-
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
23
|
-
* this list of conditions and the following disclaimer in the documentation
|
|
24
|
-
* and/or other materials provided with the distribution.
|
|
25
|
-
* 3. The name of the author may not be used to endorse or promote products
|
|
26
|
-
* derived from this software without specific prior written permission.
|
|
27
|
-
* * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
|
28
|
-
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
29
|
-
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
|
30
|
-
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
31
|
-
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
|
32
|
-
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
33
|
-
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
34
|
-
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
|
35
|
-
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
|
36
|
-
* OF SUCH DAMAGE.
|
|
37
|
-
*
|
|
38
|
-
* ------------------------------------------------------------------------------
|
|
39
|
-
* 2. html-minifier-next
|
|
40
|
-
* Repository: https://github.com/j9t/html-minifier-next
|
|
41
|
-
* Copyright (c) Jens Oliver Meiert (html-minifier-next)
|
|
42
|
-
* Copyright (c) Daniel Ruf (html-minifier-terser)
|
|
43
|
-
* Copyright (c) Juriy "kangax" Zaytsev (html-minifier)
|
|
44
|
-
* * Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
45
|
-
* of this software and associated documentation files (the "Software"), to deal
|
|
46
|
-
* in the Software without restriction, including without limitation the rights
|
|
47
|
-
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
48
|
-
* copies of the Software, and to permit persons to whom the Software is
|
|
49
|
-
* furnished to do so, subject to the following conditions:
|
|
50
|
-
* * The above copyright notice and this permission notice shall be included in
|
|
51
|
-
* all copies or substantial portions of the Software.
|
|
52
|
-
* * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
53
|
-
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
54
|
-
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
55
|
-
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
56
|
-
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
57
|
-
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
58
|
-
* THE SOFTWARE.
|
|
59
|
-
* ==============================================================================
|
|
60
|
-
*/
|
|
61
|
-
|
|
62
|
-
import express from 'express';
|
|
63
|
-
import open from 'open';
|
|
64
|
-
import path from 'node:path';
|
|
65
|
-
import { fileURLToPath } from 'node:url';
|
|
66
|
-
import { runMakeFsData, MakeFsDataOptions } from './makefsdata.js';
|
|
67
|
-
import { getPackageVersion } from './utils.js';
|
|
68
|
-
import { execSync } from 'node:child_process';
|
|
69
|
-
import os from 'node:os';
|
|
70
|
-
|
|
71
|
-
// prevent socket errors
|
|
72
|
-
process.on('uncaughtException', (err: any) => {
|
|
73
|
-
if (err.code === 'EADDRINUSE') return;
|
|
74
|
-
console.error('⚠️ Uncaught Error:', err);
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
const __filename: string = fileURLToPath(import.meta.url);
|
|
78
|
-
const __dirname: string = path.dirname(__filename);
|
|
79
|
-
const app = express();
|
|
80
|
-
|
|
81
|
-
// port set by command
|
|
82
|
-
let PORT: number = parseInt(process.env.PORT || '3000', 10);
|
|
83
|
-
const portArgIndex = process.argv.indexOf('--port');
|
|
84
|
-
if (portArgIndex !== -1 && process.argv[portArgIndex + 1]) {
|
|
85
|
-
const parsedPort = parseInt(process.argv[portArgIndex + 1]!, 10);
|
|
86
|
-
if (!isNaN(parsedPort)) PORT = parsedPort;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
let server: any;
|
|
90
|
-
let shutdownTimer: NodeJS.Timeout | null = null;
|
|
91
|
-
|
|
92
|
-
app.use(express.json());
|
|
93
|
-
app.use(express.static(path.join(__dirname, '../public')));
|
|
94
|
-
|
|
95
|
-
const cancelShutdown = () => {
|
|
96
|
-
if (shutdownTimer) {
|
|
97
|
-
clearTimeout(shutdownTimer);
|
|
98
|
-
shutdownTimer = null;
|
|
99
|
-
// console.log('🛡️ Shutdown cancelled (keep alive)');
|
|
100
|
-
}
|
|
101
|
-
};
|
|
102
|
-
|
|
103
|
-
app.get('/api/version', (_req, res) => {
|
|
104
|
-
cancelShutdown();
|
|
105
|
-
res.json({ version: getPackageVersion() });
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
app.post('/api/shutdown', (_req, res) => {
|
|
109
|
-
res.json({ success: true });
|
|
110
|
-
|
|
111
|
-
if (! shutdownTimer) {
|
|
112
|
-
shutdownTimer = setTimeout(() => {
|
|
113
|
-
console.log('👋 Window closed, shutting down ...');
|
|
114
|
-
process.exit(0);
|
|
115
|
-
}, 2000);
|
|
116
|
-
}
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
app.post('/api/cancel-shutdown', (_req, res) => {
|
|
120
|
-
cancelShutdown();
|
|
121
|
-
res.json({ success: true });
|
|
122
|
-
});
|
|
123
|
-
|
|
124
|
-
app.post('/api/build', async (req: express.Request, res: express.Response): Promise<void> => {
|
|
125
|
-
cancelShutdown();
|
|
126
|
-
const { inputPath, outputPath, minifyOpts } = req.body;
|
|
127
|
-
|
|
128
|
-
console.log(`[Build] Input: ${inputPath}`);
|
|
129
|
-
console.log(`[Build] Output: ${outputPath}`);
|
|
130
|
-
|
|
131
|
-
const opts: MakeFsDataOptions = {
|
|
132
|
-
inputDir: inputPath,
|
|
133
|
-
outputFile: outputPath,
|
|
134
|
-
processSubs: true,
|
|
135
|
-
includeHttpHeader: true,
|
|
136
|
-
useHttp11: false,
|
|
137
|
-
supportSsi: true,
|
|
138
|
-
precalcChksum: false,
|
|
139
|
-
minifyOpts: minifyOpts
|
|
140
|
-
};
|
|
141
|
-
|
|
142
|
-
try {
|
|
143
|
-
// get stats
|
|
144
|
-
const stats = await runMakeFsData(opts);
|
|
145
|
-
|
|
146
|
-
try {
|
|
147
|
-
await open(path.dirname(path.resolve(outputPath)));
|
|
148
|
-
}
|
|
149
|
-
catch (e) {
|
|
150
|
-
// ignore open folder error
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
// return stats
|
|
154
|
-
res.json({
|
|
155
|
-
success: true,
|
|
156
|
-
stats: stats // originalSize, compressedSize, filesCount
|
|
157
|
-
});
|
|
158
|
-
}
|
|
159
|
-
catch (error: any) {
|
|
160
|
-
res.json({ success: false, message: error.message });
|
|
161
|
-
}
|
|
162
|
-
});
|
|
163
|
-
|
|
164
|
-
app.post('/api/change-port', (req: express.Request, res: express.Response): void => {
|
|
165
|
-
cancelShutdown();
|
|
166
|
-
const parsedPort = parseInt(req.body.newPort, 10);
|
|
167
|
-
|
|
168
|
-
if (isNaN(parsedPort) || parsedPort < 1 || parsedPort > 65535) {
|
|
169
|
-
res.json({ success: false, message: 'Invalid port number.' });
|
|
170
|
-
return;
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
res.json({ success: true });
|
|
174
|
-
|
|
175
|
-
setTimeout(() => {
|
|
176
|
-
if (server) {
|
|
177
|
-
try {
|
|
178
|
-
server.closeAllConnections();
|
|
179
|
-
server.close(() => {
|
|
180
|
-
PORT = parsedPort;
|
|
181
|
-
startServer();
|
|
182
|
-
console.log(`🔄 Server successfully restarted on port ${PORT}`);
|
|
183
|
-
});
|
|
184
|
-
}
|
|
185
|
-
catch (e) {
|
|
186
|
-
startServer();
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
}, 100);
|
|
190
|
-
});
|
|
191
|
-
|
|
192
|
-
app.get('/api/browse', (req, res) => {
|
|
193
|
-
const isDir = req.query.type === 'dir';
|
|
194
|
-
const platform = os.platform();
|
|
195
|
-
let command = '';
|
|
196
|
-
|
|
197
|
-
try {
|
|
198
|
-
if (platform === 'win32') { // Windows: Powershell + OpenFileDialog
|
|
199
|
-
if (isDir) command = `powershell -Command "Add-Type -AssemblyName System.Windows.Forms; $f = New-Object System.Windows.Forms.OpenFileDialog; $f.CheckFileExists = $false; $f.CheckPathExists = $true; $f.FileName = 'Select Folder'; $f.ValidateNames = $false; if($f.ShowDialog() -eq 'OK'){ Split-Path $f.FileName }"`;
|
|
200
|
-
else command = `powershell -Command "Add-Type -AssemblyName System.Windows.Forms; $f = New-Object System.Windows.Forms.OpenFileDialog; $f.Filter = 'C Files (*.c)|*.c|All Files (*.*)|*.*'; if($f.ShowDialog() -eq 'OK'){ $f.FileName }"`;
|
|
201
|
-
}
|
|
202
|
-
else if (platform === 'darwin') { // macOS: darwin
|
|
203
|
-
if (isDir) command = `osascript -e 'POSIX path of (choose folder with prompt "Select Input Directory")'`;
|
|
204
|
-
else command = `osascript -e 'POSIX path of (choose file with prompt "Select Output File")'`;
|
|
205
|
-
}
|
|
206
|
-
else { // Linux: Zenity
|
|
207
|
-
if (isDir) command = `zenity --file-selection --directory --title="Select Input Directory"`;
|
|
208
|
-
else command = `zenity --file-selection --title="Select Output File"`;
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
const result = execSync(command).toString().trim();
|
|
212
|
-
res.json({ success: true, path: result || null });
|
|
213
|
-
}
|
|
214
|
-
catch (e) {
|
|
215
|
-
res.json({ success: true, path: null });
|
|
216
|
-
}
|
|
217
|
-
});
|
|
218
|
-
|
|
219
|
-
const startServer = () => {
|
|
220
|
-
server = app.listen(PORT, () => {
|
|
221
|
-
console.log(`✨ GUI Server started on http://localhost:${PORT}`);
|
|
222
|
-
});
|
|
223
|
-
};
|
|
224
|
-
|
|
225
|
-
// main run
|
|
226
|
-
startServer();
|
|
227
|
-
open(`http://localhost:${PORT}`);
|
package/src/makefsdata.ts
DELETED
|
@@ -1,390 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* ==============================================================================
|
|
3
|
-
* CC4EmbeddedSystem V3 (makefsdata)
|
|
4
|
-
* Copyright (c) 2026 LunaticGhoulPiano / Emile Su
|
|
5
|
-
* Licensed under the MIT License.
|
|
6
|
-
* ==============================================================================
|
|
7
|
-
*
|
|
8
|
-
* This software integrates concepts, logic, and minification processes derived
|
|
9
|
-
* from the following open-source projects. We deeply appreciate their work:
|
|
10
|
-
*
|
|
11
|
-
* ------------------------------------------------------------------------------
|
|
12
|
-
* 1. lwIP (Lightweight TCP/IP stack)
|
|
13
|
-
* Repository: https://github.com/m-labs/lwip
|
|
14
|
-
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
|
15
|
-
* All rights reserved.
|
|
16
|
-
* * Redistribution and use in source and binary forms, with or without modification,
|
|
17
|
-
* are permitted provided that the following conditions are met:
|
|
18
|
-
* * 1. Redistributions of source code must retain the above copyright notice,
|
|
19
|
-
* this list of conditions and the following disclaimer.
|
|
20
|
-
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
21
|
-
* this list of conditions and the following disclaimer in the documentation
|
|
22
|
-
* and/or other materials provided with the distribution.
|
|
23
|
-
* 3. The name of the author may not be used to endorse or promote products
|
|
24
|
-
* derived from this software without specific prior written permission.
|
|
25
|
-
* * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
|
26
|
-
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
27
|
-
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
|
28
|
-
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
29
|
-
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
|
30
|
-
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
31
|
-
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
32
|
-
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
|
33
|
-
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
|
34
|
-
* OF SUCH DAMAGE.
|
|
35
|
-
*
|
|
36
|
-
* ------------------------------------------------------------------------------
|
|
37
|
-
* 2. html-minifier-next
|
|
38
|
-
* Repository: https://github.com/j9t/html-minifier-next
|
|
39
|
-
* Copyright (c) Jens Oliver Meiert (html-minifier-next)
|
|
40
|
-
* Copyright (c) Daniel Ruf (html-minifier-terser)
|
|
41
|
-
* Copyright (c) Juriy "kangax" Zaytsev (html-minifier)
|
|
42
|
-
* * Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
43
|
-
* of this software and associated documentation files (the "Software"), to deal
|
|
44
|
-
* in the Software without restriction, including without limitation the rights
|
|
45
|
-
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
46
|
-
* copies of the Software, and to permit persons to whom the Software is
|
|
47
|
-
* furnished to do so, subject to the following conditions:
|
|
48
|
-
* * The above copyright notice and this permission notice shall be included in
|
|
49
|
-
* all copies or substantial portions of the Software.
|
|
50
|
-
* * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
51
|
-
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
52
|
-
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
53
|
-
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
54
|
-
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
55
|
-
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
56
|
-
* THE SOFTWARE.
|
|
57
|
-
* ==============================================================================
|
|
58
|
-
*/
|
|
59
|
-
|
|
60
|
-
// modern ESM
|
|
61
|
-
import fs from 'node:fs';
|
|
62
|
-
import path from 'node:path';
|
|
63
|
-
import { minify } from 'html-minifier-next';
|
|
64
|
-
import { getPackageVersion } from './utils.js';
|
|
65
|
-
|
|
66
|
-
// ----------------------------------------------------------------------
|
|
67
|
-
// 1. Configs & Version Recovery
|
|
68
|
-
// ----------------------------------------------------------------------
|
|
69
|
-
const TCP_MSS: number = 1460;
|
|
70
|
-
const LWIP_VERSION: string = "1.3.1"; // this makefsdata.ts is based on lwIP v1.3.1
|
|
71
|
-
|
|
72
|
-
// html-minifier-next options
|
|
73
|
-
const COMPRESS_OPTS_DEFAULT = {
|
|
74
|
-
collapseWhitespace: true,
|
|
75
|
-
removeComments: true,
|
|
76
|
-
minifyJS: true,
|
|
77
|
-
minifyCSS: true,
|
|
78
|
-
processConditionalComments: true,
|
|
79
|
-
decodeEntities: true
|
|
80
|
-
};
|
|
81
|
-
|
|
82
|
-
export interface MakeFsDataOptions {
|
|
83
|
-
inputDir: string;
|
|
84
|
-
outputFile: string;
|
|
85
|
-
processSubs: boolean;
|
|
86
|
-
includeHttpHeader: boolean;
|
|
87
|
-
useHttp11: boolean;
|
|
88
|
-
supportSsi: boolean;
|
|
89
|
-
precalcChksum: boolean;
|
|
90
|
-
minifyOpts?: any; // customize
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
// ----------------------------------------------------------------------
|
|
94
|
-
// 2. Structures
|
|
95
|
-
// ----------------------------------------------------------------------
|
|
96
|
-
interface ChksumBlock { offset: number; chksum: number; len: number; }
|
|
97
|
-
interface HeaderPart { str: string; buf: Buffer; }
|
|
98
|
-
interface FileEntry {
|
|
99
|
-
varName: string; pathName: string; nameBuffer: Buffer;
|
|
100
|
-
headerParts: HeaderPart[]; headerTotalBuffer: Buffer;
|
|
101
|
-
contentBuffer: Buffer; chksums: ChksumBlock[];
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
// ----------------------------------------------------------------------
|
|
105
|
-
// 3. lwIP Helpers
|
|
106
|
-
// ----------------------------------------------------------------------
|
|
107
|
-
function getMimeType(fileName: string): string {
|
|
108
|
-
const ext: string = path.extname(fileName).toLowerCase();
|
|
109
|
-
switch (ext) {
|
|
110
|
-
case '.html':
|
|
111
|
-
case '.htm':
|
|
112
|
-
case '.shtml':
|
|
113
|
-
case '.shtm':
|
|
114
|
-
case '.ssi': {
|
|
115
|
-
return 'text/html';
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
case '.css':
|
|
119
|
-
return 'text/css';
|
|
120
|
-
case '.js':
|
|
121
|
-
return 'application/javascript';
|
|
122
|
-
case '.png':
|
|
123
|
-
return 'image/png';
|
|
124
|
-
case '.gif':
|
|
125
|
-
return 'image/gif';
|
|
126
|
-
|
|
127
|
-
case '.jpg':
|
|
128
|
-
case '.jpeg': {
|
|
129
|
-
return 'image/jpeg';
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
case '.ico':
|
|
133
|
-
return 'image/x-icon';
|
|
134
|
-
case '.xml':
|
|
135
|
-
return 'text/xml';
|
|
136
|
-
case '.json':
|
|
137
|
-
return 'application/json';
|
|
138
|
-
default:
|
|
139
|
-
return 'text/plain';
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
function inetChksum(buf: Buffer): number {
|
|
144
|
-
let sum: number = 0;
|
|
145
|
-
for (let i = 0; i < buf.length; i += 2) {
|
|
146
|
-
const b1: number | undefined = buf[i];
|
|
147
|
-
const b2: number | undefined = (i + 1 < buf.length) ? buf[i + 1] : 0;
|
|
148
|
-
|
|
149
|
-
if (b1 === undefined) continue;
|
|
150
|
-
sum += (b1 << 8) | (b2 ?? 0);
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
while (sum >> 16) sum = (sum & 0xFFFF) + (sum >> 16);
|
|
154
|
-
|
|
155
|
-
return (~sum) & 0xFFFF;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
function generateHttpHeaders(fileName: string, dataLength: number, opts: MakeFsDataOptions): { parts: HeaderPart[], totalBuffer: Buffer } {
|
|
159
|
-
const parts: HeaderPart[] = [];
|
|
160
|
-
const ccVersion = getPackageVersion();
|
|
161
|
-
const addPart = (str: string) => { parts.push({ str, buf: Buffer.from(str, 'ascii') }); };
|
|
162
|
-
|
|
163
|
-
const baseName: string = path.basename(fileName);
|
|
164
|
-
const ext: string = path.extname(fileName).toLowerCase();
|
|
165
|
-
|
|
166
|
-
const protocol: string = opts.useHttp11 ? "HTTP/1.1" : "HTTP/1.0";
|
|
167
|
-
if (baseName.startsWith("404")) addPart(`${protocol} 404 File not found\r\n`);
|
|
168
|
-
else if (baseName.startsWith("400")) addPart(`${protocol} 400 Bad Request\r\n`);
|
|
169
|
-
else if (baseName.startsWith("501")) addPart(`${protocol} 501 Not Implemented\r\n`);
|
|
170
|
-
else addPart(`${protocol} 200 OK\r\n`);
|
|
171
|
-
|
|
172
|
-
const serverInfo = `Server: lwIP & CC4EmbeddedSystem V3\r\n` +
|
|
173
|
-
`lwIP (${LWIP_VERSION}): (http://savannah.nongnu.org/projects/lwip)\r\n` +
|
|
174
|
-
`CC4EmbeddedSystem V3 (${ccVersion}): https://github.com/LunaticGhoulPiano/CC4EmbeddedSystem\r\n`;
|
|
175
|
-
parts.push({ str: serverInfo, buf: Buffer.alloc(0) }); // addPart(serverInfo);
|
|
176
|
-
|
|
177
|
-
let isSsi: boolean = false;
|
|
178
|
-
if (opts.supportSsi && ['.shtml', '.shtm', '.ssi', '.xml'].includes(ext)) isSsi = true;
|
|
179
|
-
|
|
180
|
-
if (opts.useHttp11) {
|
|
181
|
-
if (! isSsi) {
|
|
182
|
-
addPart(`Content-Length: ${dataLength}\r\n`);
|
|
183
|
-
addPart(`Connection: keep-alive\r\n`);
|
|
184
|
-
}
|
|
185
|
-
else addPart(`Connection: close\r\n`);
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
addPart(`Content-type: ${getMimeType(fileName)}\r\n\r\n`);
|
|
189
|
-
|
|
190
|
-
return { parts, totalBuffer: Buffer.concat(parts.map(p => p.buf)) };
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
function getFilesRecursive(dir: string, processSubs: boolean): string[] {
|
|
194
|
-
const results: string[] = [];
|
|
195
|
-
if (! fs.existsSync(dir)) return results;
|
|
196
|
-
const list: string[] = fs.readdirSync(dir);
|
|
197
|
-
|
|
198
|
-
for (const file of list) {
|
|
199
|
-
const fullPath: string = path.join(dir, file);
|
|
200
|
-
const stat: fs.Stats = fs.statSync(fullPath);
|
|
201
|
-
if (! stat.isDirectory()) results.push(fullPath);
|
|
202
|
-
else if (processSubs) results.push(...getFilesRecursive(fullPath, processSubs));
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
return results;
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
function bufferToHexCArray(buf: Buffer): string {
|
|
209
|
-
let out = '';
|
|
210
|
-
for (let i = 0; i < buf.length; i++) {
|
|
211
|
-
if (i % 16 === 0) out += '\t';
|
|
212
|
-
const b: number | undefined = buf[i];
|
|
213
|
-
if (b === undefined) continue;
|
|
214
|
-
out += `0x${b.toString(16).padStart(2, '0')},`;
|
|
215
|
-
if ((i + 1) % 16 === 0) out += '\n';
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
if (!out.endsWith('\n')) out += '\n';
|
|
219
|
-
|
|
220
|
-
return out;
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
// ----------------------------------------------------------------------
|
|
224
|
-
// 4. export API
|
|
225
|
-
// ----------------------------------------------------------------------
|
|
226
|
-
|
|
227
|
-
export interface BuildStats {
|
|
228
|
-
originalSize: number;
|
|
229
|
-
compressedSize: number;
|
|
230
|
-
filesCount: number;
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
export async function runMakeFsData(opts: MakeFsDataOptions): Promise<BuildStats> {
|
|
234
|
-
console.log(`🚀 CC4EmbeddedSystem V3: Starting makefsdata compilation...`);
|
|
235
|
-
|
|
236
|
-
// checkers
|
|
237
|
-
if (! fs.existsSync(opts.inputDir)) {
|
|
238
|
-
console.log(`⚠️ Input directory not found. Auto-creating directory: \n${opts.inputDir}`);
|
|
239
|
-
fs.mkdirSync(opts.inputDir, { recursive: true });
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
if (!opts.outputFile.toLowerCase().endsWith('.c')) {
|
|
243
|
-
opts.outputFile += '.c';
|
|
244
|
-
console.log(`🔧 Auto-appended '.c' to output file -> ${opts.outputFile}`);
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
const outDir = path.dirname(opts.outputFile);
|
|
248
|
-
if (! fs.existsSync(outDir)) fs.mkdirSync(outDir, { recursive: true });
|
|
249
|
-
|
|
250
|
-
const allFiles = getFilesRecursive(opts.inputDir, opts.processSubs);
|
|
251
|
-
const fileEntries: FileEntry[] = [];
|
|
252
|
-
let totalOriginalSize = 0;
|
|
253
|
-
let totalCompressedSize = 0;
|
|
254
|
-
|
|
255
|
-
if (allFiles.length === 0) throw new Error(`Input directory is empty! Please put your web files (.html, .css, etc.) into:\n${path.resolve(opts.inputDir)}`);
|
|
256
|
-
|
|
257
|
-
// html-minifier-next options
|
|
258
|
-
const activeCompressOpts = opts.minifyOpts || COMPRESS_OPTS_DEFAULT;
|
|
259
|
-
|
|
260
|
-
for (let i = 0; i < allFiles.length; i++) {
|
|
261
|
-
const filePath = allFiles[i]!;
|
|
262
|
-
const relativePath = '/' + path.relative(opts.inputDir, filePath).replace(/\\/g, '/');
|
|
263
|
-
const ext = path.extname(filePath).toLowerCase();
|
|
264
|
-
let content = fs.readFileSync(filePath);
|
|
265
|
-
|
|
266
|
-
const originalFileSize = content.length;
|
|
267
|
-
totalOriginalSize += originalFileSize;
|
|
268
|
-
|
|
269
|
-
if (['.html', '.htm', '.css', '.js'].includes(ext)) {
|
|
270
|
-
const minifiedStr = await minify(content.toString('utf8'), activeCompressOpts);
|
|
271
|
-
|
|
272
|
-
if (typeof minifiedStr === 'string') {
|
|
273
|
-
content = Buffer.from(minifiedStr, 'utf8');
|
|
274
|
-
console.log(`📦 Minified: ${relativePath} (${originalFileSize} -> ${content.length} bytes)`);
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
else console.log(`📄 Copied: ${relativePath}`);
|
|
278
|
-
|
|
279
|
-
totalCompressedSize += content.length;
|
|
280
|
-
|
|
281
|
-
// generate header
|
|
282
|
-
const headerData = opts.includeHttpHeader ? generateHttpHeaders(filePath, content.length, opts) : { parts: [], totalBuffer: Buffer.alloc(0) };
|
|
283
|
-
const nameBuffer = Buffer.from(relativePath + '\0', 'utf8');
|
|
284
|
-
const varName = relativePath.replace(/[^A-Za-z0-9]/g, '_');
|
|
285
|
-
|
|
286
|
-
const chksums: ChksumBlock[] = [];
|
|
287
|
-
if (opts.precalcChksum) {
|
|
288
|
-
let offset = 0;
|
|
289
|
-
|
|
290
|
-
if (headerData.totalBuffer.length > 0) {
|
|
291
|
-
chksums.push({ offset: 0, chksum: inetChksum(headerData.totalBuffer), len: headerData.totalBuffer.length });
|
|
292
|
-
offset += headerData.totalBuffer.length;
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
for (let chunkOffset = 0; chunkOffset < content.length; chunkOffset += TCP_MSS) {
|
|
296
|
-
const chunkLen = Math.min(TCP_MSS, content.length - chunkOffset);
|
|
297
|
-
chksums.push({ offset: offset, chksum: inetChksum(content.subarray(chunkOffset, chunkOffset + chunkLen)), len: chunkLen });
|
|
298
|
-
offset += chunkLen;
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
fileEntries.push({ varName, pathName: relativePath, nameBuffer, headerParts: headerData.parts, headerTotalBuffer: headerData.totalBuffer, contentBuffer: content, chksums });
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
// ====================================================================
|
|
306
|
-
// C Code Generation
|
|
307
|
-
// ====================================================================
|
|
308
|
-
let cOutput: string = `/* Generated by CC4EmbeddedSystem V3 (makefsdata) */\n\n`;
|
|
309
|
-
cOutput += `#include "fs.h"\n#include "lwip/def.h"\n#include "fsdata.h"\n\n\n`;
|
|
310
|
-
cOutput += `#define file_NULL (struct fsdata_file *) NULL\n\n\n`;
|
|
311
|
-
|
|
312
|
-
if (opts.precalcChksum) {
|
|
313
|
-
cOutput += `#if HTTPD_PRECALCULATED_CHECKSUM\n`;
|
|
314
|
-
for (const file of fileEntries) {
|
|
315
|
-
cOutput += `const struct fsdata_chksum chksums_${file.varName}[] = {\n`;
|
|
316
|
-
for (const chk of file.chksums) cOutput += `\t{${chk.offset}, 0x${chk.chksum.toString(16).padStart(4, '0')}, ${chk.len}},\n`;
|
|
317
|
-
cOutput += `};\n`;
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
cOutput += `#endif /* HTTPD_PRECALCULATED_CHECKSUM */\n\n\n`;
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
// generate data arrays
|
|
324
|
-
for (const file of fileEntries) {
|
|
325
|
-
cOutput += `static const unsigned int dummy_align_${file.varName} = 0;\n`;
|
|
326
|
-
cOutput += `static const unsigned char data_${file.varName}[] = {\n`;
|
|
327
|
-
cOutput += `\t/* ${file.pathName} (${file.nameBuffer.length} chars) */\n`;
|
|
328
|
-
cOutput += bufferToHexCArray(file.nameBuffer);
|
|
329
|
-
|
|
330
|
-
if (file.headerParts.length > 0) {
|
|
331
|
-
cOutput += `\n\t/* HTTP header */\n`;
|
|
332
|
-
for (const part of file.headerParts) {
|
|
333
|
-
let finalStr = part.str.replace(/\n/g, '\n\t');
|
|
334
|
-
if (finalStr.endsWith('\t')) finalStr = finalStr.slice(0, -1);
|
|
335
|
-
cOutput += `\t/* "${finalStr}\t" (${part.buf.length} bytes) */\n`;
|
|
336
|
-
cOutput += bufferToHexCArray(part.buf);
|
|
337
|
-
}
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
cOutput += `\n\t/* raw file data (${file.contentBuffer.length} bytes) */\n`;
|
|
341
|
-
cOutput += bufferToHexCArray(file.contentBuffer);
|
|
342
|
-
cOutput += `};\n\n\n\n`;
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
// redirhome.html
|
|
346
|
-
cOutput += `/* --- Empty arrays --- */\n`;
|
|
347
|
-
cOutput += `static const unsigned char data__redirhome_html[] = {};\n`;
|
|
348
|
-
cOutput += `const struct fsdata_file file__redirhome_html[] = { {\n`;
|
|
349
|
-
cOutput += `\tfile_NULL,\n`;
|
|
350
|
-
cOutput += `\tdata__redirhome_html,\n`;
|
|
351
|
-
cOutput += `\tdata__redirhome_html + 16,\n`;
|
|
352
|
-
cOutput += `\tsizeof(data__redirhome_html) - 16,\n`;
|
|
353
|
-
cOutput += `\t1,\n`;
|
|
354
|
-
|
|
355
|
-
// checksum
|
|
356
|
-
if (opts.precalcChksum) cOutput += `#if HTTPD_PRECALCULATED_CHECKSUM\n\t0, NULL,\n#endif /* HTTPD_PRECALCULATED_CHECKSUM */\n`;
|
|
357
|
-
cOutput += `}};\n\n\n`;
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
// generate linked-list
|
|
361
|
-
for (let i = fileEntries.length - 1; i >= 0; i--) {
|
|
362
|
-
const current = fileEntries[i]!;
|
|
363
|
-
|
|
364
|
-
// last element didn't points to file_NULL but file__redirhome_html
|
|
365
|
-
const nextVar = fileEntries[i + 1] ? `file_${fileEntries[i+1]!.varName}` : 'file__redirhome_html';
|
|
366
|
-
const nameLen = current.nameBuffer.length;
|
|
367
|
-
|
|
368
|
-
// address: e.g. "/index.html\0" = '/' + 'i' + 'n' + 'd' + 'e' + 'x' + '.' + 'h' + 't' + 'm' + 'l' + '\0' = 12
|
|
369
|
-
cOutput += `const struct fsdata_file file_${current.varName}[] = { {\n`;
|
|
370
|
-
cOutput += `\t${nextVar},\n\tdata_${current.varName},\n\tdata_${current.varName} + ${nameLen},\n\tsizeof(data_${current.varName}) - ${nameLen},\n\t${opts.includeHttpHeader ? 1 : 0},\n`;
|
|
371
|
-
|
|
372
|
-
if (opts.precalcChksum) cOutput += `#if HTTPD_PRECALCULATED_CHECKSUM\n\t${current.chksums.length}, chksums_${current.varName},\n#endif /* HTTPD_PRECALCULATED_CHECKSUM */\n`;
|
|
373
|
-
cOutput += `}};\n\n`;
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
const rootNode = fileEntries[0];
|
|
377
|
-
if (rootNode) {
|
|
378
|
-
cOutput += `#define FS_ROOT file_${rootNode.varName}\n#define FS_NUMFILES ${fileEntries.length + 1}\n`;
|
|
379
|
-
fs.writeFileSync(opts.outputFile, cOutput);
|
|
380
|
-
console.log(`\n✨ Success! Output written to: ${opts.outputFile}`);
|
|
381
|
-
|
|
382
|
-
return {
|
|
383
|
-
originalSize: totalOriginalSize,
|
|
384
|
-
compressedSize: totalCompressedSize,
|
|
385
|
-
filesCount: fileEntries.length
|
|
386
|
-
};
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
throw new Error("No files processed.");
|
|
390
|
-
}
|
package/src/utils.ts
DELETED
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* ==============================================================================
|
|
3
|
-
* CC4EmbeddedSystem V3 (makefsdata)
|
|
4
|
-
* Copyright (c) 2026 LunaticGhoulPiano / Emile Su
|
|
5
|
-
* Licensed under the MIT License.
|
|
6
|
-
* ==============================================================================
|
|
7
|
-
*
|
|
8
|
-
* This software integrates concepts, logic, and minification processes derived
|
|
9
|
-
* from the following open-source projects. We deeply appreciate their work:
|
|
10
|
-
*
|
|
11
|
-
* ------------------------------------------------------------------------------
|
|
12
|
-
* 1. lwIP (Lightweight TCP/IP stack)
|
|
13
|
-
* Repository: https://github.com/m-labs/lwip
|
|
14
|
-
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
|
15
|
-
* All rights reserved.
|
|
16
|
-
* * Redistribution and use in source and binary forms, with or without modification,
|
|
17
|
-
* are permitted provided that the following conditions are met:
|
|
18
|
-
* * 1. Redistributions of source code must retain the above copyright notice,
|
|
19
|
-
* this list of conditions and the following disclaimer.
|
|
20
|
-
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
21
|
-
* this list of conditions and the following disclaimer in the documentation
|
|
22
|
-
* and/or other materials provided with the distribution.
|
|
23
|
-
* 3. The name of the author may not be used to endorse or promote products
|
|
24
|
-
* derived from this software without specific prior written permission.
|
|
25
|
-
* * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
|
26
|
-
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
27
|
-
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
|
28
|
-
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
29
|
-
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
|
30
|
-
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
31
|
-
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
32
|
-
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
|
33
|
-
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
|
34
|
-
* OF SUCH DAMAGE.
|
|
35
|
-
*
|
|
36
|
-
* ------------------------------------------------------------------------------
|
|
37
|
-
* 2. html-minifier-next
|
|
38
|
-
* Repository: https://github.com/j9t/html-minifier-next
|
|
39
|
-
* Copyright (c) Jens Oliver Meiert (html-minifier-next)
|
|
40
|
-
* Copyright (c) Daniel Ruf (html-minifier-terser)
|
|
41
|
-
* Copyright (c) Juriy "kangax" Zaytsev (html-minifier)
|
|
42
|
-
* * Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
43
|
-
* of this software and associated documentation files (the "Software"), to deal
|
|
44
|
-
* in the Software without restriction, including without limitation the rights
|
|
45
|
-
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
46
|
-
* copies of the Software, and to permit persons to whom the Software is
|
|
47
|
-
* furnished to do so, subject to the following conditions:
|
|
48
|
-
* * The above copyright notice and this permission notice shall be included in
|
|
49
|
-
* all copies or substantial portions of the Software.
|
|
50
|
-
* * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
51
|
-
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
52
|
-
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
53
|
-
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
54
|
-
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
55
|
-
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
56
|
-
* THE SOFTWARE.
|
|
57
|
-
* ==============================================================================
|
|
58
|
-
*/
|
|
59
|
-
|
|
60
|
-
import fs from 'node:fs';
|
|
61
|
-
import path from 'node:path';
|
|
62
|
-
import { fileURLToPath } from 'node:url';
|
|
63
|
-
|
|
64
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
65
|
-
const __dirname = path.dirname(__filename);
|
|
66
|
-
|
|
67
|
-
export const getPackageVersion = (): string => {
|
|
68
|
-
try {
|
|
69
|
-
const pkgPath = path.join(__dirname, '../package.json');
|
|
70
|
-
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
|
|
71
|
-
return pkg.version || "LTS";
|
|
72
|
-
}
|
|
73
|
-
catch (error) {
|
|
74
|
-
return "LTS";
|
|
75
|
-
}
|
|
76
|
-
};
|
package/tsconfig.json
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
/* environment */
|
|
4
|
-
"target": "ES2022",
|
|
5
|
-
"module": "NodeNext",
|
|
6
|
-
"moduleResolution": "NodeNext",
|
|
7
|
-
"rootDir": "./src",
|
|
8
|
-
"outDir": "./dist",
|
|
9
|
-
|
|
10
|
-
/* strict type checking */
|
|
11
|
-
"strict": true,
|
|
12
|
-
"noImplicitAny": true, /* no "any" */
|
|
13
|
-
"strictNullChecks": true,
|
|
14
|
-
"noUncheckedIndexedAccess": true,
|
|
15
|
-
"exactOptionalPropertyTypes": true,
|
|
16
|
-
|
|
17
|
-
/* Coding style */
|
|
18
|
-
"noUnusedLocals": true,
|
|
19
|
-
"noUnusedParameters": true,
|
|
20
|
-
"noImplicitReturns": true,
|
|
21
|
-
|
|
22
|
-
/* module and consistency */
|
|
23
|
-
"esModuleInterop": true,
|
|
24
|
-
"forceConsistentCasingInFileNames": true,
|
|
25
|
-
"skipLibCheck": true,
|
|
26
|
-
"types": ["node"]
|
|
27
|
-
},
|
|
28
|
-
"include": ["src/**/*"]
|
|
29
|
-
}
|
|
File without changes
|