svelteesp32 1.11.0 → 1.12.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
@@ -12,6 +12,10 @@ In order to be able to easily update OTA, it is important - from the users' poin
12
12
 
13
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
14
 
15
+ > Starting with version v1.12.0, you can use RC file for configuration
16
+
17
+ > Starting with version v1.11.0, you can exclude files by pattern
18
+
15
19
  > Starting with version v1.10.0, we reduced npm dependencies
16
20
 
17
21
  > Starting with version v1.9.0, code generator for esp-idf is available
@@ -84,13 +88,13 @@ npm run fix
84
88
 
85
89
  ### Usage
86
90
 
87
- **Install package** as devDependency (it is practical if the package is part of the project so that you always receive updates)
91
+ **Install package** as dev dependency (it is practical if the package is part of the project so that you always receive updates)
88
92
 
89
93
  ```bash
90
94
  npm install -D svelteesp32
91
95
  ```
92
96
 
93
- After a successful Svelte build (rollup/webpack/vite) **create an includeable c++ header** file
97
+ After a successful Svelte build (rollup/webpack/vite) **create an includable c++ header** file
94
98
 
95
99
  ```bash
96
100
  // for PsychicHttpServer
@@ -425,8 +429,117 @@ You can use the following c++ directives at the project level if you want to con
425
429
  | `--version` | Include a version string in generated header, e.g. `--version=v$npm_package_version` | '' |
426
430
  | `--espmethod` | Name of generated initialization method | `initSvelteStaticFiles` |
427
431
  | `--define` | Prefix of c++ defines (e.g., SVELTEESP32_COUNT) | `SVELTEESP32` |
432
+ | `--config` | Use custom RC file path | `.svelteesp32rc.json` |
428
433
  | `-h` | Show help | |
429
434
 
435
+ ### Configuration File
436
+
437
+ You can store frequently-used options in a configuration file to avoid repeating command line arguments. This is especially useful for CI/CD pipelines and team collaboration.
438
+
439
+ #### Quick Start
440
+
441
+ Create `.svelteesp32rc.json` in your project directory:
442
+
443
+ ```json
444
+ {
445
+ "engine": "psychic",
446
+ "sourcepath": "./dist",
447
+ "outputfile": "./esp32/include/svelteesp32.h",
448
+ "etag": "true",
449
+ "gzip": "true",
450
+ "cachetime": 86400,
451
+ "exclude": ["*.map", "*.md"]
452
+ }
453
+ ```
454
+
455
+ Then simply run:
456
+
457
+ ```bash
458
+ npx svelteesp32
459
+ ```
460
+
461
+ No command line arguments needed!
462
+
463
+ #### Search Locations
464
+
465
+ The tool automatically searches for `.svelteesp32rc.json` in:
466
+
467
+ 1. Current working directory
468
+ 2. User home directory
469
+
470
+ Or specify a custom location:
471
+
472
+ ```bash
473
+ npx svelteesp32 --config=.svelteesp32rc.prod.json
474
+ ```
475
+
476
+ #### Configuration Reference
477
+
478
+ All CLI options can be specified in the RC file using long-form property names:
479
+
480
+ | RC Property | CLI Flag | Type | Example |
481
+ | ------------ | ------------- | ------- | ------------------------------------------------ |
482
+ | `engine` | `-e` | string | `"psychic"`, `"psychic2"`, `"async"`, `"espidf"` |
483
+ | `sourcepath` | `-s` | string | `"./dist"` |
484
+ | `outputfile` | `-o` | string | `"./output.h"` |
485
+ | `etag` | `--etag` | string | `"true"`, `"false"`, `"compiler"` |
486
+ | `gzip` | `--gzip` | string | `"true"`, `"false"`, `"compiler"` |
487
+ | `cachetime` | `--cachetime` | number | `86400` |
488
+ | `created` | `--created` | boolean | `true`, `false` |
489
+ | `version` | `--version` | string | `"v1.0.0"` |
490
+ | `espmethod` | `--espmethod` | string | `"initSvelteStaticFiles"` |
491
+ | `define` | `--define` | string | `"SVELTEESP32"` |
492
+ | `exclude` | `--exclude` | array | `["*.map", "*.md"]` |
493
+
494
+ #### CLI Override
495
+
496
+ Command line arguments always take precedence over RC file values:
497
+
498
+ ```bash
499
+ # Use RC settings but override etag
500
+ npx svelteesp32 --etag=false
501
+
502
+ # Use RC settings but add different exclude pattern
503
+ npx svelteesp32 --exclude="*.txt"
504
+ ```
505
+
506
+ #### Multiple Environments
507
+
508
+ Create different config files for different environments:
509
+
510
+ ```bash
511
+ # Development build
512
+ npx svelteesp32 --config=.svelteesp32rc.dev.json
513
+
514
+ # Production build
515
+ npx svelteesp32 --config=.svelteesp32rc.prod.json
516
+ ```
517
+
518
+ #### Exclude Pattern Behavior
519
+
520
+ **Replace mode**: When you specify `exclude` patterns in RC file or CLI, they completely replace the defaults.
521
+
522
+ - **No exclude specified**: Uses default system exclusions (`.DS_Store`, `Thumbs.db`, `.git`, etc.)
523
+ - **RC file has exclude**: Replaces defaults with RC patterns
524
+ - **CLI has --exclude**: Replaces RC patterns (or defaults if no RC)
525
+
526
+ Example:
527
+
528
+ ```json
529
+ // .svelteesp32rc.json
530
+ { "exclude": ["*.map"] }
531
+ ```
532
+
533
+ Result: Only `*.map` is excluded (default patterns are replaced)
534
+
535
+ To keep defaults, explicitly list them in your RC file:
536
+
537
+ ```json
538
+ {
539
+ "exclude": [".DS_Store", "Thumbs.db", ".git", "*.map", "*.md"]
540
+ }
541
+ ```
542
+
430
543
  ### Q&A
431
544
 
432
545
  - **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.
@@ -1,11 +1,20 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
3
6
  exports.cmdLine = void 0;
4
7
  const node_fs_1 = require("node:fs");
8
+ const node_os_1 = require("node:os");
9
+ const node_path_1 = __importDefault(require("node:path"));
10
+ const consoleColor_1 = require("./consoleColor");
5
11
  function showHelp() {
6
12
  console.log(`
7
13
  svelteesp32 - Svelte JS to ESP32 converter
8
14
 
15
+ Configuration:
16
+ --config <path> Use custom RC file (default: search for .svelteesp32rc.json)
17
+
9
18
  Options:
10
19
  -e, --engine <value> The engine for which the include file is created
11
20
  (psychic|psychic2|async|espidf) (default: "psychic")
@@ -21,6 +30,23 @@ Options:
21
30
  --exclude <pattern> Exclude files matching glob pattern (repeatable or comma-separated)
22
31
  Examples: --exclude="*.map" --exclude="test/**/*.ts"
23
32
  -h, --help Shows this help
33
+
34
+ RC File:
35
+ The tool searches for .svelteesp32rc.json in:
36
+ 1. Current directory (./.svelteesp32rc.json)
37
+ 2. User home directory (~/.svelteesp32rc.json)
38
+
39
+ Example RC file (all fields optional):
40
+ {
41
+ "engine": "psychic",
42
+ "sourcepath": "./dist",
43
+ "outputfile": "./output.h",
44
+ "etag": "true",
45
+ "gzip": "true",
46
+ "exclude": ["*.map", "*.md"]
47
+ }
48
+
49
+ CLI arguments override RC file values.
24
50
  `);
25
51
  process.exit(0);
26
52
  }
@@ -44,8 +70,95 @@ const DEFAULT_EXCLUDE_PATTERNS = [
44
70
  '.gitignore',
45
71
  '.gitattributes'
46
72
  ];
73
+ function findRcFile(customConfigPath) {
74
+ if (customConfigPath) {
75
+ if ((0, node_fs_1.existsSync)(customConfigPath))
76
+ return customConfigPath;
77
+ throw new Error(`Config file not found: ${customConfigPath}`);
78
+ }
79
+ for (const filename of ['.svelteesp32rc.json', '.svelteesp32rc']) {
80
+ const cwdPath = node_path_1.default.join(process.cwd(), filename);
81
+ if ((0, node_fs_1.existsSync)(cwdPath))
82
+ return cwdPath;
83
+ }
84
+ const homeDirectory = (0, node_os_1.homedir)();
85
+ for (const filename of ['.svelteesp32rc.json', '.svelteesp32rc']) {
86
+ const homePath = node_path_1.default.join(homeDirectory, filename);
87
+ if ((0, node_fs_1.existsSync)(homePath))
88
+ return homePath;
89
+ }
90
+ return undefined;
91
+ }
92
+ function loadRcFile(rcPath) {
93
+ try {
94
+ const content = (0, node_fs_1.readFileSync)(rcPath, 'utf8');
95
+ const config = JSON.parse(content);
96
+ return validateRcConfig(config, rcPath);
97
+ }
98
+ catch (error) {
99
+ if (error instanceof SyntaxError)
100
+ throw new Error(`Invalid JSON in RC file ${rcPath}: ${error.message}`);
101
+ throw error;
102
+ }
103
+ }
104
+ function validateRcConfig(config, rcPath) {
105
+ if (typeof config !== 'object' || config === null)
106
+ throw new Error(`RC file ${rcPath} must contain a JSON object`);
107
+ const configObject = config;
108
+ const validKeys = new Set([
109
+ 'engine',
110
+ 'sourcepath',
111
+ 'outputfile',
112
+ 'espmethod',
113
+ 'define',
114
+ 'gzip',
115
+ 'etag',
116
+ 'cachetime',
117
+ 'created',
118
+ 'version',
119
+ 'exclude'
120
+ ]);
121
+ for (const key of Object.keys(configObject))
122
+ if (!validKeys.has(key))
123
+ console.warn((0, consoleColor_1.yellowLog)(`Warning: Unknown property '${key}' in RC file ${rcPath}`));
124
+ if (configObject['engine'] !== undefined)
125
+ configObject['engine'] = validateEngine(configObject['engine']);
126
+ if (configObject['etag'] !== undefined)
127
+ configObject['etag'] = validateTriState(configObject['etag'], 'etag');
128
+ if (configObject['gzip'] !== undefined)
129
+ configObject['gzip'] = validateTriState(configObject['gzip'], 'gzip');
130
+ if (configObject['cachetime'] !== undefined &&
131
+ (typeof configObject['cachetime'] !== 'number' || Number.isNaN(configObject['cachetime'])))
132
+ throw new TypeError(`Invalid cachetime in RC file: ${configObject['cachetime']}`);
133
+ if (configObject['exclude'] !== undefined) {
134
+ if (!Array.isArray(configObject['exclude']))
135
+ throw new TypeError("'exclude' in RC file must be an array");
136
+ for (const pattern of configObject['exclude'])
137
+ if (typeof pattern !== 'string')
138
+ throw new TypeError('All exclude patterns must be strings');
139
+ }
140
+ return configObject;
141
+ }
47
142
  function parseArguments() {
48
143
  const arguments_ = process.argv.slice(2);
144
+ let customConfigPath;
145
+ for (let index = 0; index < arguments_.length; index++) {
146
+ const argument = arguments_[index];
147
+ if (!argument)
148
+ continue;
149
+ if (argument === '--config' && arguments_[index + 1]) {
150
+ customConfigPath = arguments_[index + 1];
151
+ break;
152
+ }
153
+ if (argument.startsWith('--config=')) {
154
+ customConfigPath = argument.slice('--config='.length);
155
+ break;
156
+ }
157
+ }
158
+ const rcPath = findRcFile(customConfigPath);
159
+ const rcConfig = rcPath ? loadRcFile(rcPath) : {};
160
+ if (rcPath)
161
+ console.log((0, consoleColor_1.cyanLog)(`[SvelteESP32] Using config from: ${rcPath}`));
49
162
  const result = {
50
163
  engine: 'psychic',
51
164
  outputfile: 'svelteesp32.h',
@@ -58,6 +171,29 @@ function parseArguments() {
58
171
  cachetime: 0,
59
172
  exclude: [...DEFAULT_EXCLUDE_PATTERNS]
60
173
  };
174
+ if (rcConfig.engine)
175
+ result.engine = rcConfig.engine;
176
+ if (rcConfig.sourcepath)
177
+ result.sourcepath = rcConfig.sourcepath;
178
+ if (rcConfig.outputfile)
179
+ result.outputfile = rcConfig.outputfile;
180
+ if (rcConfig.etag)
181
+ result.etag = rcConfig.etag;
182
+ if (rcConfig.gzip)
183
+ result.gzip = rcConfig.gzip;
184
+ if (rcConfig.cachetime !== undefined)
185
+ result.cachetime = rcConfig.cachetime;
186
+ if (rcConfig.created !== undefined)
187
+ result.created = rcConfig.created;
188
+ if (rcConfig.version)
189
+ result.version = rcConfig.version;
190
+ if (rcConfig.espmethod)
191
+ result.espmethod = rcConfig.espmethod;
192
+ if (rcConfig.define)
193
+ result.define = rcConfig.define;
194
+ if (rcConfig.exclude && rcConfig.exclude.length > 0)
195
+ result.exclude = [...rcConfig.exclude];
196
+ const cliExclude = [];
61
197
  for (let index = 0; index < arguments_.length; index++) {
62
198
  const argument = arguments_[index];
63
199
  if (!argument)
@@ -72,6 +208,8 @@ function parseArguments() {
72
208
  throw new Error(`Invalid argument format: ${argument}`);
73
209
  const flagName = flag.slice(2);
74
210
  switch (flagName) {
211
+ case 'config':
212
+ break;
75
213
  case 'engine':
76
214
  result.engine = validateEngine(value);
77
215
  break;
@@ -106,8 +244,7 @@ function parseArguments() {
106
244
  .split(',')
107
245
  .map((p) => p.trim())
108
246
  .filter(Boolean);
109
- result.exclude = result.exclude || [...DEFAULT_EXCLUDE_PATTERNS];
110
- result.exclude.push(...patterns);
247
+ cliExclude.push(...patterns);
111
248
  break;
112
249
  }
113
250
  default:
@@ -148,6 +285,9 @@ function parseArguments() {
148
285
  if (!nextArgument || nextArgument.startsWith('-'))
149
286
  throw new Error(`Missing value for flag: ${argument}`);
150
287
  switch (flag) {
288
+ case 'config':
289
+ index++;
290
+ break;
151
291
  case 'engine':
152
292
  result.engine = validateEngine(nextArgument);
153
293
  index++;
@@ -191,8 +331,7 @@ function parseArguments() {
191
331
  .split(',')
192
332
  .map((p) => p.trim())
193
333
  .filter(Boolean);
194
- result.exclude = result.exclude || [...DEFAULT_EXCLUDE_PATTERNS];
195
- result.exclude.push(...patterns);
334
+ cliExclude.push(...patterns);
196
335
  index++;
197
336
  break;
198
337
  }
@@ -203,8 +342,10 @@ function parseArguments() {
203
342
  }
204
343
  throw new Error(`Unknown argument: ${argument}`);
205
344
  }
345
+ if (cliExclude.length > 0)
346
+ result.exclude = [...cliExclude];
206
347
  if (!result.sourcepath) {
207
- console.error('Error: --sourcepath is required');
348
+ console.error('Error: --sourcepath is required (can be specified in RC file or CLI)');
208
349
  showHelp();
209
350
  }
210
351
  return result;
package/dist/file.js CHANGED
@@ -63,12 +63,12 @@ const getFiles = () => {
63
63
  return true;
64
64
  });
65
65
  if (excludedFiles.length > 0) {
66
- console.log((0, consoleColor_1.cyanLog)(`\n Excluded ${excludedFiles.length} file(s):`));
66
+ console.log(`\nExcluded ${excludedFiles.length} file(s):`);
67
67
  const displayLimit = 10;
68
68
  for (const file of excludedFiles.slice(0, displayLimit))
69
- console.log((0, consoleColor_1.cyanLog)(` - ${file}`));
69
+ console.log((0, consoleColor_1.cyanLog)(`- ${file}`));
70
70
  if (excludedFiles.length > displayLimit)
71
- console.log((0, consoleColor_1.cyanLog)(` ... and ${excludedFiles.length - displayLimit} more`));
71
+ console.log((0, consoleColor_1.cyanLog)(`... and ${excludedFiles.length - displayLimit} more`));
72
72
  console.log();
73
73
  }
74
74
  const result = new Map();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "svelteesp32",
3
- "version": "1.11.0",
3
+ "version": "1.12.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",