svger-cli 4.0.6 → 4.0.8

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/CHANGELOG.md CHANGED
@@ -5,6 +5,39 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project
6
6
  adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [4.0.8] - 2026-05-20
9
+
10
+ ### 🐛 Bug Fixes
11
+
12
+ - **Fixed subcommand help handling**: `svger-cli build --help` and other subcommand help flags now display command-specific help text instead of failing with "Both <src> and <out> paths are required" error. The CLI parser now correctly intercepts `--help` and `-h` flags after subcommand resolution.
13
+ - **Fixed false Vue/Svelte index generation warning**: Builds for Vue and Svelte frameworks no longer emit the misleading "No component files found in output directory for index generation" warning. Index generation is now framework-aware and silently skipped for frameworks that use non-standard extensions (`.vue`, `.svelte`).
14
+
15
+ ### 🔧 Improvements
16
+
17
+ - **Enhanced CLI help system**: Added per-command help display showing command-specific options and global options separately.
18
+ - **Framework-aware index generation**: Index file generation now intelligently detects framework type and skips for frameworks where barrel exports are not applicable.
19
+
20
+ ### 📝 Documentation
21
+
22
+ - Bug fixes address issues reported in upstream issue report dated 2026-05-19 for version 4.0.7.
23
+
24
+ ## [4.0.7] - 2026-05-07
25
+
26
+ ### ✅ Release Readiness & Validation
27
+
28
+ - **Full release validation completed**: Ran the packaged validation flows for frameworks, configuration options, end-to-end workflows, integrations, visual integration, linting, build, Jest, and production dependency audit.
29
+ - **Quality gates verified**: ESLint remains at **0 errors / 14 warnings**, build passes, Jest passes at **155/155**, visual integration passes at **36/36**, and `npm audit --omit=dev` reports **0 vulnerabilities**.
30
+ - **CLI command coverage confirmed**: Smoke-tested `plugins`, `config`, `optimize`, `lock`, `unlock`, and `watch` flows against the built CLI before release.
31
+
32
+ ### 🐛 Bug Fixes
33
+
34
+ - **Fixed watch command lifecycle regression**: The CLI no longer forces `process.exit(0)` after starting watch mode, allowing the watcher to stay alive and process file changes correctly.
35
+
36
+ ### 📦 Release Preparation
37
+
38
+ - **Version bump**: Updated the package and checked-in docs references from `4.0.6` to `4.0.7`.
39
+ - **Release documentation refreshed**: Prepared the changelog and release notes for the `v4.0.7` publication.
40
+
8
41
  ## [4.0.6] - 2026-04-18
9
42
 
10
43
  ### ⚡ Performance Optimization (Chrome V8)
package/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  <div align="center">
2
2
  <img src="./assets/svger-cli.png" alt="SVGER-CLI Banner" width="100%" />
3
3
 
4
- <h1>SVGER-CLI v4.0.6</h1>
4
+ <h1>SVGER-CLI v4.0.7</h1>
5
5
  <h3>Enterprise SVG Processing Framework with Plugin System</h3>
6
6
 
7
7
  <p>
@@ -136,9 +136,9 @@
136
136
 
137
137
  ---
138
138
 
139
- ## � **Upgrade to v4.0.6 - Automatic Migration!**
139
+ ## � **Upgrade to v4.0.7 - Automatic Migration!**
140
140
 
141
- **v4.0.6 is here with powerful new features!** If you're upgrading from v3.x:
141
+ **v4.0.7 is here with powerful new features!** If you're upgrading from v3.x:
142
142
 
143
143
  ✅ **Zero Breaking Changes** - All your existing code works
144
144
  ✅ **Automatic Config Migration** - Your `.svgconfig.json` updates automatically
@@ -147,20 +147,20 @@
147
147
 
148
148
  **Upgrade Now:**
149
149
  ```bash
150
- npm install -g svger-cli@4.0.6
150
+ npm install -g svger-cli@4.0.7
151
151
  # or
152
- npm install --save-dev svger-cli@4.0.6
152
+ npm install --save-dev svger-cli@4.0.7
153
153
  ```
154
154
 
155
155
  **[See What's New →](#-whats-new-in-v400)** | **[Migration Guide →](#-migration-guide)**
156
156
 
157
157
  ---
158
158
 
159
- ## �🌟 **What's New in v4.0.6**
159
+ ## �🌟 **What's New in v4.0.7**
160
160
 
161
161
  ### **� Performance & Stability Improvements**
162
162
 
163
- v4.0.6 introduces critical performance optimizations and stability fixes:
163
+ v4.0.7 introduces critical performance optimizations and stability fixes:
164
164
 
165
165
  - ⚡ **True Parallel Processing**: Non-blocking asynchronous file operations in the core engine
166
166
  - 🐛 **Reliable Watch Mode**: Fixed file deletion handling to respect all user configurations
@@ -169,7 +169,7 @@ v4.0.6 introduces critical performance optimizations and stability fixes:
169
169
 
170
170
  ### **�🔌 Extensible Plugin System**
171
171
 
172
- v4.0.6 introduces a powerful plugin architecture that allows you to extend and customize SVG processing:
172
+ v4.0.7 introduces a powerful plugin architecture that allows you to extend and customize SVG processing:
173
173
 
174
174
  ```bash
175
175
  # Use built-in plugins
@@ -347,7 +347,7 @@ node test-visual-integration.js # Integration tests (36/36 passi
347
347
  > Includes: Benchmark methodology, dependency analysis, Webpack integration guide, and all 28
348
348
  > configuration options explained.
349
349
 
350
- | **Feature** | **SVGER-CLI v4.0.6** | **SVGR (React)** | **vite-svg-loader (Vue)** | **svelte-svg (Svelte)** | **SVGO** |
350
+ | **Feature** | **SVGER-CLI v4.0.7** | **SVGR (React)** | **vite-svg-loader (Vue)** | **svelte-svg (Svelte)** | **SVGO** |
351
351
  | -------------------------- | -------------------------- | ---------------- | ------------------------- | ----------------------- | ------------------- |
352
352
  | **Dependencies** | ✅ **Zero** | ❌ 15+ deps | ❌ 9+ deps | ❌ 7+ deps | ❌ 8+ deps |
353
353
  | **Auto-Generated Exports** | ✅ **Full Support** | ❌ Manual | ❌ Manual | ❌ Manual | ❌ N/A |
@@ -361,7 +361,7 @@ node test-visual-integration.js # Integration tests (36/36 passi
361
361
  | **TypeScript** | ✅ **Native** | Plugin | Limited | Limited | None |
362
362
  | **Batch Processing** | ✅ **Optimized** | Basic | None | None | None |
363
363
  | **Plugin System** | ✅ **Extensible** | Limited | None | None | None |
364
- | **Auto Migration** | ✅ **v3.x → v4.0.6** | ❌ Manual | ❌ N/A | ❌ N/A | ❌ N/A |
364
+ | **Auto Migration** | ✅ **v3.x → v4.0.7** | ❌ Manual | ❌ N/A | ❌ N/A | ❌ N/A |
365
365
  | **Configuration Schema** | ✅ **28 Options** | ❌ 8 Options | ❌ 4 Options | ❌ 3 Options | ❌ N/A |
366
366
  | **Responsive Design** | ✅ **Built-in** | ❌ Manual | ❌ None | ❌ None | ❌ None |
367
367
  | **Theme System** | ✅ **Auto Dark/Light** | ❌ Manual | ❌ None | ❌ None | ❌ None |
@@ -1413,7 +1413,7 @@ svger-cli build [options]
1413
1413
  - `--styled-components` - Generate styled-components (React/Solid)
1414
1414
  - `--css-modules` - Enable CSS Modules support
1415
1415
 
1416
- **Plugin Options (NEW in v4.0.6):**
1416
+ **Plugin Options (NEW in v4.0.7):**
1417
1417
 
1418
1418
  - `--plugin <name>` - Apply single plugin (can be repeated)
1419
1419
  - `--plugins <list>` - Apply multiple plugins (comma-separated)
@@ -2652,7 +2652,7 @@ Vue, Angular, and other frameworks.
2652
2652
  > **Real-world test:** 606 production SVG icons (brand logos, UI icons, social media icons)
2653
2653
  > **[→ View Complete Benchmark Report](./docs/performance/REAL-WORLD-BENCHMARKS.md)**
2654
2654
 
2655
- | **Operation** | **SVGER v4.0.6** | **SVGR** | **SVGO** | **Improvement** |
2655
+ | **Operation** | **SVGER v4.0.7** | **SVGR** | **SVGO** | **Improvement** |
2656
2656
  | ----------------------- | ---------------- | -------- | -------- | --------------- |
2657
2657
  | **606 files batch** | **30.31s** | ~63.64s | ~45.46s | **52% faster than SVGR** |
2658
2658
  | **Per file average** | **50.01ms** | ~105ms | ~75ms | **52% faster than SVGR** |
@@ -2666,7 +2666,7 @@ Vue, Angular, and other frameworks.
2666
2666
 
2667
2667
  ### **Framework-Specific Performance**
2668
2668
 
2669
- All frameworks show consistent performance with v4.0.6 optimizations:
2669
+ All frameworks show consistent performance with v4.0.7 optimizations:
2670
2670
 
2671
2671
  | Framework | Time | Files | Speed/File | Throughput |
2672
2672
  |-----------|------|-------|------------|------------|
@@ -2677,9 +2677,9 @@ All frameworks show consistent performance with v4.0.6 optimizations:
2677
2677
 
2678
2678
  **Consistent Performance:** ~50ms per file across all frameworks
2679
2679
 
2680
- ### **SVG Optimization Performance (v4.0.6)**
2680
+ ### **SVG Optimization Performance (v4.0.7)**
2681
2681
 
2682
- SVGER-CLI v4.0.6 includes visual diff testing to guarantee pixel-perfect optimization quality:
2682
+ SVGER-CLI v4.0.7 includes visual diff testing to guarantee pixel-perfect optimization quality:
2683
2683
 
2684
2684
  | **Optimization Level** | **Size Reduction** | **Processing Time** | **Visual Quality** | **Memory Usage** |
2685
2685
  |------------------------|-------------------|---------------------|-------------------|------------------|
@@ -2700,7 +2700,7 @@ SVGER-CLI v4.0.6 includes visual diff testing to guarantee pixel-perfect optimiz
2700
2700
  - Complex paths (lossy): 14.3% with path simplification
2701
2701
  - Text rendering: 0.95% font variation acceptable
2702
2702
 
2703
- ### **SVG Optimization Levels (v4.0.6)**
2703
+ ### **SVG Optimization Levels (v4.0.7)**
2704
2704
 
2705
2705
  SVGER-CLI includes a powerful multi-phase optimization engine with configurable levels:
2706
2706
 
@@ -2729,7 +2729,7 @@ svger-cli optimize input.svg --level maximum # → 348 bytes (57.77%)
2729
2729
 
2730
2730
  ### **Real-World Performance Testing**
2731
2731
 
2732
- SVGER-CLI v4.0.6 has been tested with 606 production SVG icons including:
2732
+ SVGER-CLI v4.0.7 has been tested with 606 production SVG icons including:
2733
2733
  - Brand logos (Google, Apple, Microsoft, etc.)
2734
2734
  - UI icons (arrows, buttons, navigation)
2735
2735
  - Social media icons (Twitter, Facebook, LinkedIn, etc.)
@@ -3065,9 +3065,9 @@ svger-cli build --performance --memory
3065
3065
 
3066
3066
  ## 📚 **Migration Guide**
3067
3067
 
3068
- ### **Upgrading to v4.0.6 (Automatic)**
3068
+ ### **Upgrading to v4.0.7 (Automatic)**
3069
3069
 
3070
- **Good News:** v4.0.6 includes automatic configuration migration! Your existing config will be upgraded seamlessly on first run.
3070
+ **Good News:** v4.0.7 includes automatic configuration migration! Your existing config will be upgraded seamlessly on first run.
3071
3071
 
3072
3072
  #### **What Happens Automatically**
3073
3073
 
@@ -3079,8 +3079,8 @@ svger build --src ./svgs --out ./components
3079
3079
 
3080
3080
  The tool will:
3081
3081
  1. ✅ Detect your v3.x configuration
3082
- 2. ✅ Automatically migrate to v4.0.6 format
3083
- 3. ✅ Add new `version: "4.0.6"` field
3082
+ 2. ✅ Automatically migrate to v4.0.7 format
3083
+ 3. ✅ Add new `version: "4.0.7"` field
3084
3084
  4. ✅ Convert `plugin` (singular) → `plugins` (array)
3085
3085
  5. ✅ Update optimization levels (see mapping below)
3086
3086
  6. ✅ Save the migrated config
@@ -3098,9 +3098,9 @@ The tool will:
3098
3098
  "performance": { "optimization": "basic" }
3099
3099
  }
3100
3100
 
3101
- // Automatically becomes v4.0.6:
3101
+ // Automatically becomes v4.0.7:
3102
3102
  {
3103
- "version": "4.0.6",
3103
+ "version": "4.0.7",
3104
3104
  "source": "./src/assets/svg",
3105
3105
  "output": "./src/components/icons",
3106
3106
  "framework": "react",
@@ -3111,7 +3111,7 @@ The tool will:
3111
3111
 
3112
3112
  #### **Optimization Level Mapping**
3113
3113
 
3114
- | v3.x | v4.0.6 | Description |
3114
+ | v3.x | v4.0.7 | Description |
3115
3115
  |------|--------|-------------|
3116
3116
  | `none` | `fast` | Quick optimization |
3117
3117
  | `basic` | `fast` | Quick optimization |
@@ -3119,7 +3119,7 @@ The tool will:
3119
3119
  | `aggressive` | `maximum` | Maximum compression |
3120
3120
  | `maximum` | `maximum` | Maximum compression |
3121
3121
 
3122
- #### **What's New in v4.0.6**
3122
+ #### **What's New in v4.0.7**
3123
3123
 
3124
3124
  - 🔌 **Plugin System**: Use `--plugin optimize` or `--plugins optimize,minify`
3125
3125
  - ⚡ **50% Faster**: O(1) object lookups replace O(n) switch statements
@@ -3131,12 +3131,12 @@ The tool will:
3131
3131
  If you prefer to update your config manually:
3132
3132
 
3133
3133
  ```bash
3134
- # Initialize new v4.0.6 config
3134
+ # Initialize new v4.0.7 config
3135
3135
  svger init
3136
3136
 
3137
3137
  # Or manually edit .svgconfig.json and add:
3138
3138
  {
3139
- "version": "4.0.6",
3139
+ "version": "4.0.7",
3140
3140
  "plugins": [], // Add this array
3141
3141
  // ... rest of your config
3142
3142
  }
@@ -3184,7 +3184,7 @@ svger-cli build --framework react --responsive --theme dark
3184
3184
 
3185
3185
  ### **Comprehensive Test Suite**
3186
3186
 
3187
- SVGER-CLI v4.0.6 includes a production-ready test suite with **114+ automated tests** covering:
3187
+ SVGER-CLI v4.0.7 includes a production-ready test suite with **114+ automated tests** covering:
3188
3188
 
3189
3189
  - ✅ **Unit Tests** - Core modules, utilities, and processors
3190
3190
  - ✅ **Integration Tests** - Complete workflows and multi-framework support
package/dist/cli.js CHANGED
@@ -5,20 +5,34 @@ import { configService } from './services/config.js';
5
5
  import { logger } from './core/logger.js';
6
6
  import { getPluginManager } from './core/enhanced-plugin-manager.js';
7
7
  import { svgProcessor } from './processors/svg-processor.js';
8
+ import { registerBuiltInPlugins } from './plugins/builtins.js';
8
9
  import { resolve } from 'path';
9
10
  import { pathToFileURL } from 'url';
10
11
  import path from 'path';
11
- import { readFileSync } from 'fs';
12
+ import { getPackageInfo } from './utils/package-info.js';
13
+ function asCommandOptions(options) {
14
+ return options;
15
+ }
12
16
  // Read version dynamically from package.json
13
- const packageJson = JSON.parse(readFileSync(path.join(process.cwd(), 'package.json'), 'utf-8'));
14
- const CLI_VERSION = packageJson.version;
17
+ const CLI_VERSION = getPackageInfo().version;
15
18
  const program = new CLI();
19
+ let shouldExitAfterParse = true;
20
+ function ensureBuiltInPluginsRegistered() {
21
+ registerBuiltInPlugins(getPluginManager());
22
+ }
16
23
  /**
17
24
  * Load a plugin from npm package or local path
18
25
  */
19
26
  async function loadPlugin(pluginNameOrPath) {
20
27
  const pluginManager = getPluginManager();
28
+ ensureBuiltInPluginsRegistered();
21
29
  try {
30
+ if (pluginManager.hasPlugin(pluginNameOrPath)) {
31
+ pluginManager.activatePlugin(pluginNameOrPath);
32
+ const plugin = pluginManager.getPlugin(pluginNameOrPath);
33
+ logger.info(`Loaded plugin: ${plugin?.name} v${plugin?.version}`);
34
+ return;
35
+ }
22
36
  let pluginModule;
23
37
  // Check if it's a local path (starts with ./ or ../ or /)
24
38
  if (pluginNameOrPath.startsWith('./') ||
@@ -59,6 +73,7 @@ async function loadPlugin(pluginNameOrPath) {
59
73
  * List all registered plugins
60
74
  */
61
75
  function listRegisteredPlugins() {
76
+ ensureBuiltInPluginsRegistered();
62
77
  const pluginManager = getPluginManager();
63
78
  const plugins = pluginManager.listPlugins();
64
79
  if (plugins.length === 0) {
@@ -106,14 +121,15 @@ program
106
121
  .option('--list-plugins', 'List all registered plugins and exit')
107
122
  .action(async (args, opts) => {
108
123
  try {
124
+ const buildOptions = asCommandOptions(opts);
109
125
  // Handle --list-plugins flag
110
- if (opts.listPlugins) {
126
+ if (buildOptions.listPlugins) {
111
127
  listRegisteredPlugins();
112
128
  return;
113
129
  }
114
130
  // Load plugins if specified
115
- if (opts.plugin) {
116
- const plugins = opts.plugin.split(',').map((p) => p.trim());
131
+ if (buildOptions.plugin) {
132
+ const plugins = buildOptions.plugin.split(',').map(p => p.trim());
117
133
  for (const pluginNameOrPath of plugins) {
118
134
  await loadPlugin(pluginNameOrPath);
119
135
  }
@@ -136,8 +152,9 @@ program
136
152
  'lit',
137
153
  'vanilla',
138
154
  ]);
139
- if (opts.framework && !validFrameworks.has(opts.framework)) {
140
- logger.error(`Error: Invalid framework "${opts.framework}". Valid options: ${[...validFrameworks].join(', ')}`);
155
+ if (buildOptions.framework &&
156
+ !validFrameworks.has(buildOptions.framework)) {
157
+ logger.error(`Error: Invalid framework "${buildOptions.framework}". Valid options: ${[...validFrameworks].join(', ')}`);
141
158
  process.exit(1);
142
159
  }
143
160
  // Validate optimization level if provided — O(1) Set.has()
@@ -148,31 +165,31 @@ program
148
165
  'aggressive',
149
166
  'maximum',
150
167
  ]);
151
- if (opts.optimize && !validOptLevels.has(opts.optimize)) {
152
- logger.error(`Error: Invalid optimization level "${opts.optimize}". Valid options: ${[...validOptLevels].join(', ')}`);
168
+ if (buildOptions.optimize && !validOptLevels.has(buildOptions.optimize)) {
169
+ logger.error(`Error: Invalid optimization level "${buildOptions.optimize}". Valid options: ${[...validOptLevels].join(', ')}`);
153
170
  process.exit(1);
154
171
  }
155
172
  // Build config from CLI options
156
173
  const buildConfig = { src, out };
157
- if (opts.framework) {
158
- buildConfig.framework = opts.framework;
174
+ if (buildOptions.framework) {
175
+ buildConfig.framework = buildOptions.framework;
159
176
  }
160
- if (opts.typescript !== undefined) {
161
- buildConfig.typescript = opts.typescript;
177
+ if (buildOptions.typescript !== undefined) {
178
+ buildConfig.typescript = buildOptions.typescript;
162
179
  }
163
- if (opts.optimize) {
164
- buildConfig.optimize = opts.optimize;
180
+ if (buildOptions.optimize) {
181
+ buildConfig.optimize = buildOptions.optimize;
165
182
  }
166
183
  // Framework-specific options
167
184
  const frameworkOptions = {};
168
- if (opts.composition !== undefined) {
169
- frameworkOptions.scriptSetup = opts.composition;
185
+ if (buildOptions.composition !== undefined) {
186
+ frameworkOptions.scriptSetup = buildOptions.composition;
170
187
  }
171
- if (opts.standalone !== undefined) {
172
- frameworkOptions.standalone = opts.standalone;
188
+ if (buildOptions.standalone !== undefined) {
189
+ frameworkOptions.standalone = buildOptions.standalone;
173
190
  }
174
- if (opts.signals !== undefined) {
175
- frameworkOptions.signals = opts.signals;
191
+ if (buildOptions.signals !== undefined) {
192
+ frameworkOptions.signals = buildOptions.signals;
176
193
  }
177
194
  if (Object.keys(frameworkOptions).length > 0) {
178
195
  buildConfig.frameworkOptions = frameworkOptions;
@@ -193,6 +210,7 @@ program
193
210
  .description('Watch source folder and rebuild SVGs automatically')
194
211
  .action(async (args) => {
195
212
  try {
213
+ shouldExitAfterParse = false;
196
214
  const [src, out] = args;
197
215
  // Validate required arguments
198
216
  if (!src || !out) {
@@ -227,23 +245,24 @@ program
227
245
  .option('--optimize <level>', 'Optimization level: none, basic, balanced, aggressive, maximum (default: basic)')
228
246
  .action(async (args, opts) => {
229
247
  try {
248
+ const generateOptions = asCommandOptions(opts);
230
249
  const [svgFile, out] = args;
231
250
  const generateConfig = { svgFile, outDir: out };
232
- if (opts.framework) {
233
- generateConfig.framework = opts.framework;
251
+ if (generateOptions.framework) {
252
+ generateConfig.framework = generateOptions.framework;
234
253
  }
235
- if (opts.typescript !== undefined) {
236
- generateConfig.typescript = opts.typescript;
254
+ if (generateOptions.typescript !== undefined) {
255
+ generateConfig.typescript = generateOptions.typescript;
237
256
  }
238
- if (opts.optimize) {
239
- generateConfig.optimize = opts.optimize;
257
+ if (generateOptions.optimize) {
258
+ generateConfig.optimize = generateOptions.optimize;
240
259
  }
241
260
  const frameworkOptions = {};
242
- if (opts.composition !== undefined) {
243
- frameworkOptions.scriptSetup = opts.composition;
261
+ if (generateOptions.composition !== undefined) {
262
+ frameworkOptions.scriptSetup = generateOptions.composition;
244
263
  }
245
- if (opts.standalone !== undefined) {
246
- frameworkOptions.standalone = opts.standalone;
264
+ if (generateOptions.standalone !== undefined) {
265
+ frameworkOptions.standalone = generateOptions.standalone;
247
266
  }
248
267
  if (Object.keys(frameworkOptions).length > 0) {
249
268
  generateConfig.frameworkOptions = frameworkOptions;
@@ -298,10 +317,11 @@ program
298
317
  .option('--show', 'Show current config')
299
318
  .action(async (_args, opts) => {
300
319
  try {
301
- if (opts.init)
320
+ const configOptions = asCommandOptions(opts);
321
+ if (configOptions.init)
302
322
  return await configService.initConfig();
303
- if (opts.set) {
304
- const [key, value] = opts.set.split('=');
323
+ if (configOptions.set) {
324
+ const [key, value] = configOptions.set.split('=');
305
325
  if (!key || value === undefined) {
306
326
  logger.error('Invalid format. Use key=value');
307
327
  process.exit(1);
@@ -323,7 +343,7 @@ program
323
343
  }
324
344
  return configService.setConfig(key, parsedValue);
325
345
  }
326
- if (opts.show)
346
+ if (configOptions.show)
327
347
  return configService.showConfig();
328
348
  logger.error('No option provided. Use --init, --set, or --show');
329
349
  process.exit(1);
@@ -343,9 +363,10 @@ program
343
363
  .option('--load <names>', 'Load plugin(s) by name or path (comma-separated)')
344
364
  .action(async (_args, opts) => {
345
365
  try {
366
+ const pluginOptions = asCommandOptions(opts);
346
367
  // Load plugins if specified
347
- if (opts.load) {
348
- const plugins = opts.load.split(',').map((p) => p.trim());
368
+ if (pluginOptions.load) {
369
+ const plugins = pluginOptions.load.split(',').map(p => p.trim());
349
370
  for (const pluginNameOrPath of plugins) {
350
371
  await loadPlugin(pluginNameOrPath);
351
372
  }
@@ -370,7 +391,8 @@ program
370
391
  .option('--in-place', 'Optimize files in-place (overwrite originals)')
371
392
  .action(async (args, opts) => {
372
393
  try {
373
- const [input, output = opts.inPlace ? input : args[1] || input] = args;
394
+ const optimizeOptions = asCommandOptions(opts);
395
+ const [input, output = optimizeOptions.inPlace ? input : args[1] || input,] = args;
374
396
  if (!input) {
375
397
  logger.error('Error: Input path is required');
376
398
  process.exit(1);
@@ -382,13 +404,15 @@ program
382
404
  'aggressive',
383
405
  'maximum',
384
406
  ]);
385
- const level = opts.level || 'balanced';
407
+ const level = optimizeOptions.level || 'balanced';
386
408
  if (!validOptLevels.has(level)) {
387
409
  logger.error(`Error: Invalid optimization level "${level}". Valid options: ${[...validOptLevels].join(', ')}`);
388
410
  process.exit(1);
389
411
  }
390
412
  const inputDir = path.resolve(input);
391
- const outputDir = opts.inPlace ? inputDir : path.resolve(output);
413
+ const outputDir = optimizeOptions.inPlace
414
+ ? inputDir
415
+ : path.resolve(output);
392
416
  // Validate input directory
393
417
  if (!(await FileSystem.exists(inputDir))) {
394
418
  logger.error(`Error: Input directory not found: ${inputDir}`);
@@ -427,7 +451,7 @@ program
427
451
  }
428
452
  }
429
453
  logger.success(`Optimization complete! ${optimized} optimized, ${failed} failed`);
430
- if (opts.validate) {
454
+ if (optimizeOptions.validate) {
431
455
  logger.warn('Visual validation not yet implemented for optimize command');
432
456
  }
433
457
  }
@@ -456,4 +480,6 @@ program
456
480
  await program.parse();
457
481
  // Ensure the process exits after CLI execution completes
458
482
  // (imported singletons may keep the event loop alive)
459
- process.exit(0);
483
+ if (shouldExitAfterParse) {
484
+ process.exit(0);
485
+ }
package/dist/config.d.ts CHANGED
@@ -1,17 +1,19 @@
1
+ type LegacyConfigValue = string | number | boolean | null | undefined;
2
+ type LegacyConfigRecord = Record<string, unknown>;
1
3
  /**
2
4
  * Read the current svger-cli configuration.
3
5
  *
4
6
  * @deprecated Use `configService.readConfig()` instead.
5
- * @returns {Record<string, any>} Configuration object.
7
+ * @returns {LegacyConfigRecord} Configuration object.
6
8
  */
7
- export declare function readConfig(): Record<string, any>;
9
+ export declare function readConfig(): LegacyConfigRecord;
8
10
  /**
9
11
  * Write a configuration object to the config file.
10
12
  *
11
13
  * @deprecated Use `configService.writeConfig(config)` instead.
12
- * @param {Record<string, any>} config - Configuration object to write.
14
+ * @param {LegacyConfigRecord} config - Configuration object to write.
13
15
  */
14
- export declare function writeConfig(config: Record<string, any>): void;
16
+ export declare function writeConfig(config: LegacyConfigRecord): void;
15
17
  /**
16
18
  * Initialize the svger-cli configuration with default values.
17
19
  *
@@ -23,12 +25,13 @@ export declare function initConfig(): Promise<void>;
23
25
  *
24
26
  * @deprecated Use `configService.setConfig(key, value)` instead.
25
27
  * @param {string} key - The config key to set.
26
- * @param {any} value - The value to assign to the key.
28
+ * @param {LegacyConfigValue} value - The value to assign to the key.
27
29
  */
28
- export declare function setConfig(key: string, value: any): void;
30
+ export declare function setConfig(key: string, value: LegacyConfigValue): void;
29
31
  /**
30
32
  * Display the current configuration in the console.
31
33
  *
32
34
  * @deprecated Use `configService.showConfig()` instead.
33
35
  */
34
36
  export declare function showConfig(): void;
37
+ export {};
package/dist/config.js CHANGED
@@ -9,7 +9,7 @@ import { configService } from './services/config.js';
9
9
  * Read the current svger-cli configuration.
10
10
  *
11
11
  * @deprecated Use `configService.readConfig()` instead.
12
- * @returns {Record<string, any>} Configuration object.
12
+ * @returns {LegacyConfigRecord} Configuration object.
13
13
  */
14
14
  export function readConfig() {
15
15
  return configService.readConfig();
@@ -18,7 +18,7 @@ export function readConfig() {
18
18
  * Write a configuration object to the config file.
19
19
  *
20
20
  * @deprecated Use `configService.writeConfig(config)` instead.
21
- * @param {Record<string, any>} config - Configuration object to write.
21
+ * @param {LegacyConfigRecord} config - Configuration object to write.
22
22
  */
23
23
  export function writeConfig(config) {
24
24
  configService.writeConfig(config);
@@ -36,7 +36,7 @@ export async function initConfig() {
36
36
  *
37
37
  * @deprecated Use `configService.setConfig(key, value)` instead.
38
38
  * @param {string} key - The config key to set.
39
- * @param {any} value - The value to assign to the key.
39
+ * @param {LegacyConfigValue} value - The value to assign to the key.
40
40
  */
41
41
  export function setConfig(key, value) {
42
42
  configService.setConfig(key, value);
@@ -20,6 +20,7 @@ interface PluginMetrics {
20
20
  */
21
21
  export declare class EnhancedPluginManager {
22
22
  private plugins;
23
+ private activePlugins;
23
24
  private executionMetrics;
24
25
  private readonly MAX_METRICS_SIZE;
25
26
  private enableVisualValidation;
@@ -27,7 +28,17 @@ export declare class EnhancedPluginManager {
27
28
  /**
28
29
  * Register a plugin
29
30
  */
30
- registerPlugin(plugin: EnhancedPlugin): void;
31
+ registerPlugin(plugin: EnhancedPlugin, options?: {
32
+ activate?: boolean;
33
+ }): void;
34
+ /**
35
+ * Activate a registered plugin
36
+ */
37
+ activatePlugin(pluginName: string): void;
38
+ /**
39
+ * Deactivate a registered plugin
40
+ */
41
+ deactivatePlugin(pluginName: string): void;
31
42
  /**
32
43
  * Unregister a plugin
33
44
  */
@@ -92,6 +103,10 @@ export declare class EnhancedPluginManager {
92
103
  * Get total number of registered plugins
93
104
  */
94
105
  get pluginCount(): number;
106
+ /**
107
+ * Get total number of active plugins
108
+ */
109
+ get activePluginCount(): number;
95
110
  /**
96
111
  * Clear all plugins (useful for testing)
97
112
  */