svger-cli 2.0.1 → 2.0.3
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/.svgerconfig.example.json +38 -0
- package/CHANGELOG.md +64 -0
- package/DEVELOPMENT.md +353 -0
- package/README.md +24 -5
- package/SECURITY.md +69 -0
- package/dist/builder.js +16 -16
- package/dist/clean.js +2 -2
- package/dist/cli.js +38 -38
- package/dist/config.js +11 -11
- package/dist/core/error-handler.d.ts +63 -0
- package/dist/core/error-handler.js +227 -0
- package/dist/core/framework-templates.d.ts +17 -0
- package/{src/core/framework-templates.ts → dist/core/framework-templates.js} +104 -139
- package/dist/core/logger.d.ts +22 -0
- package/dist/core/logger.js +85 -0
- package/dist/core/performance-engine.d.ts +67 -0
- package/dist/core/performance-engine.js +252 -0
- package/dist/core/plugin-manager.d.ts +56 -0
- package/dist/core/plugin-manager.js +191 -0
- package/dist/core/style-compiler.d.ts +88 -0
- package/dist/core/style-compiler.js +468 -0
- package/dist/core/template-manager.d.ts +64 -0
- package/{src/core/template-manager.ts → dist/core/template-manager.js} +172 -255
- package/dist/index.d.ts +153 -0
- package/{src/index.ts → dist/index.js} +32 -110
- package/dist/lock.js +7 -7
- package/dist/processors/svg-processor.d.ts +73 -0
- package/dist/processors/svg-processor.js +261 -0
- package/dist/services/config.d.ts +55 -0
- package/dist/services/config.js +211 -0
- package/dist/services/file-watcher.d.ts +54 -0
- package/dist/services/file-watcher.js +180 -0
- package/dist/services/svg-service.d.ts +81 -0
- package/dist/services/svg-service.js +395 -0
- package/dist/templates/ComponentTemplate.js +25 -25
- package/dist/types/index.d.ts +146 -0
- package/dist/types/index.js +4 -0
- package/dist/utils/native.d.ts +104 -0
- package/dist/utils/native.js +340 -0
- package/dist/watch.d.ts +1 -1
- package/dist/watch.js +14 -14
- package/package.json +154 -14
- package/.svgconfig.json +0 -3
- package/CODE_OF_CONDUCT.md +0 -79
- package/CONTRIBUTING.md +0 -146
- package/TESTING.md +0 -143
- package/cli-framework.test.js +0 -16
- package/cli-test-angular/Arrowbenddownleft.component.ts +0 -27
- package/cli-test-angular/Vite.component.ts +0 -27
- package/cli-test-angular/index.ts +0 -25
- package/cli-test-output/Arrowbenddownleft.vue +0 -33
- package/cli-test-output/Vite.vue +0 -33
- package/cli-test-output/index.ts +0 -25
- package/cli-test-react/Arrowbenddownleft.tsx +0 -39
- package/cli-test-react/Vite.tsx +0 -39
- package/cli-test-react/index.ts +0 -25
- package/cli-test-svelte/Arrowbenddownleft.svelte +0 -22
- package/cli-test-svelte/Vite.svelte +0 -22
- package/cli-test-svelte/index.ts +0 -25
- package/frameworks.test.js +0 -170
- package/my-svgs/ArrowBendDownLeft.svg +0 -6
- package/my-svgs/vite.svg +0 -1
- package/src/builder.ts +0 -104
- package/src/clean.ts +0 -21
- package/src/cli.ts +0 -221
- package/src/config.ts +0 -81
- package/src/core/error-handler.ts +0 -303
- package/src/core/logger.ts +0 -104
- package/src/core/performance-engine.ts +0 -327
- package/src/core/plugin-manager.ts +0 -228
- package/src/core/style-compiler.ts +0 -605
- package/src/lock.ts +0 -74
- package/src/processors/svg-processor.ts +0 -288
- package/src/services/config.ts +0 -241
- package/src/services/file-watcher.ts +0 -218
- package/src/services/svg-service.ts +0 -468
- package/src/templates/ComponentTemplate.ts +0 -57
- package/src/types/index.ts +0 -169
- package/src/utils/native.ts +0 -352
- package/src/watch.ts +0 -88
- package/test-output-mulit/TestIcon-angular-module.component.ts +0 -26
- package/test-output-mulit/TestIcon-angular-standalone.component.ts +0 -27
- package/test-output-mulit/TestIcon-lit.ts +0 -35
- package/test-output-mulit/TestIcon-preact.tsx +0 -38
- package/test-output-mulit/TestIcon-react.tsx +0 -35
- package/test-output-mulit/TestIcon-solid.tsx +0 -27
- package/test-output-mulit/TestIcon-svelte.svelte +0 -22
- package/test-output-mulit/TestIcon-vanilla.ts +0 -37
- package/test-output-mulit/TestIcon-vue-composition.vue +0 -33
- package/test-output-mulit/TestIcon-vue-options.vue +0 -31
- package/tsconfig.json +0 -18
package/dist/cli.js
CHANGED
|
@@ -1,30 +1,30 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { CLI } from
|
|
3
|
-
import { svgService } from
|
|
4
|
-
import { configService } from
|
|
5
|
-
import { logger } from
|
|
2
|
+
import { CLI } from './utils/native.js';
|
|
3
|
+
import { svgService } from './services/svg-service.js';
|
|
4
|
+
import { configService } from './services/config.js';
|
|
5
|
+
import { logger } from './core/logger.js';
|
|
6
6
|
const program = new CLI();
|
|
7
7
|
/**
|
|
8
8
|
* svger-cli CLI
|
|
9
9
|
* Custom SVG to Angular, React, Vue, Svelte, Solid, and other component converter.
|
|
10
10
|
*/
|
|
11
11
|
program
|
|
12
|
-
.name(
|
|
13
|
-
.description(
|
|
14
|
-
.version(
|
|
12
|
+
.name('svger-cli')
|
|
13
|
+
.description('Custom SVG to Angular, React, Vue, Svelte, Solid, and other component converter')
|
|
14
|
+
.version('2.0.0');
|
|
15
15
|
// -------- Build Command --------
|
|
16
16
|
/**
|
|
17
17
|
* Build all SVGs from a source folder to an output folder.
|
|
18
18
|
*/
|
|
19
19
|
program
|
|
20
|
-
.command(
|
|
21
|
-
.description(
|
|
22
|
-
.option(
|
|
23
|
-
.option(
|
|
24
|
-
.option(
|
|
25
|
-
.option(
|
|
26
|
-
.option(
|
|
27
|
-
.option(
|
|
20
|
+
.command('build <src> <out>')
|
|
21
|
+
.description('Build all SVGs from source to output')
|
|
22
|
+
.option('--framework <type>', 'Target framework (react|vue|svelte|angular|solid|preact|lit|vanilla)')
|
|
23
|
+
.option('--typescript', 'Generate TypeScript components (default: true)')
|
|
24
|
+
.option('--no-typescript', 'Generate JavaScript components')
|
|
25
|
+
.option('--composition', 'Use Vue Composition API with <script setup>')
|
|
26
|
+
.option('--standalone', 'Generate Angular standalone components')
|
|
27
|
+
.option('--signals', 'Use Angular signals for reactive state')
|
|
28
28
|
.action(async (args, opts) => {
|
|
29
29
|
try {
|
|
30
30
|
const [src, out] = args;
|
|
@@ -62,8 +62,8 @@ program
|
|
|
62
62
|
* Watch a source folder and rebuild SVGs automatically on changes.
|
|
63
63
|
*/
|
|
64
64
|
program
|
|
65
|
-
.command(
|
|
66
|
-
.description(
|
|
65
|
+
.command('watch <src> <out>')
|
|
66
|
+
.description('Watch source folder and rebuild SVGs automatically')
|
|
67
67
|
.action(async (args) => {
|
|
68
68
|
try {
|
|
69
69
|
const [src, out] = args;
|
|
@@ -85,13 +85,13 @@ program
|
|
|
85
85
|
* Generate a component from a single SVG file.
|
|
86
86
|
*/
|
|
87
87
|
program
|
|
88
|
-
.command(
|
|
89
|
-
.description(
|
|
90
|
-
.option(
|
|
91
|
-
.option(
|
|
92
|
-
.option(
|
|
93
|
-
.option(
|
|
94
|
-
.option(
|
|
88
|
+
.command('generate <svgFile> <out>')
|
|
89
|
+
.description('Convert a single SVG file into a component')
|
|
90
|
+
.option('--framework <type>', 'Target framework (react|vue|svelte|angular|solid|preact|lit|vanilla)')
|
|
91
|
+
.option('--typescript', 'Generate TypeScript component (default: true)')
|
|
92
|
+
.option('--no-typescript', 'Generate JavaScript component')
|
|
93
|
+
.option('--composition', 'Use Vue Composition API with <script setup>')
|
|
94
|
+
.option('--standalone', 'Generate Angular standalone component')
|
|
95
95
|
.action(async (args, opts) => {
|
|
96
96
|
try {
|
|
97
97
|
const [svgFile, out] = args;
|
|
@@ -124,8 +124,8 @@ program
|
|
|
124
124
|
* Lock one or more SVG files to prevent accidental overwrites.
|
|
125
125
|
*/
|
|
126
126
|
program
|
|
127
|
-
.command(
|
|
128
|
-
.description(
|
|
127
|
+
.command('lock <files...>')
|
|
128
|
+
.description('Lock one or more SVG files')
|
|
129
129
|
.action((args) => {
|
|
130
130
|
try {
|
|
131
131
|
svgService.lockService.lockFiles(args);
|
|
@@ -139,8 +139,8 @@ program
|
|
|
139
139
|
* Unlock one or more SVG files to allow modifications.
|
|
140
140
|
*/
|
|
141
141
|
program
|
|
142
|
-
.command(
|
|
143
|
-
.description(
|
|
142
|
+
.command('unlock <files...>')
|
|
143
|
+
.description('Unlock one or more SVG files')
|
|
144
144
|
.action((args) => {
|
|
145
145
|
try {
|
|
146
146
|
svgService.lockService.unlockFiles(args);
|
|
@@ -155,19 +155,19 @@ program
|
|
|
155
155
|
* Manage svger-cli configuration.
|
|
156
156
|
*/
|
|
157
157
|
program
|
|
158
|
-
.command(
|
|
159
|
-
.description(
|
|
160
|
-
.option(
|
|
161
|
-
.option(
|
|
162
|
-
.option(
|
|
158
|
+
.command('config')
|
|
159
|
+
.description('Manage svger-cli configuration')
|
|
160
|
+
.option('--init', 'Create default .svgconfig.json')
|
|
161
|
+
.option('--set <keyValue>', 'Set config key=value')
|
|
162
|
+
.option('--show', 'Show current config')
|
|
163
163
|
.action(async (args, opts) => {
|
|
164
164
|
try {
|
|
165
165
|
if (opts.init)
|
|
166
166
|
return await configService.initConfig();
|
|
167
167
|
if (opts.set) {
|
|
168
|
-
const [key, value] = opts.set.split(
|
|
168
|
+
const [key, value] = opts.set.split('=');
|
|
169
169
|
if (!key || value === undefined) {
|
|
170
|
-
logger.error(
|
|
170
|
+
logger.error('Invalid format. Use key=value');
|
|
171
171
|
process.exit(1);
|
|
172
172
|
}
|
|
173
173
|
const parsedValue = !isNaN(Number(value)) ? Number(value) : value;
|
|
@@ -175,7 +175,7 @@ program
|
|
|
175
175
|
}
|
|
176
176
|
if (opts.show)
|
|
177
177
|
return configService.showConfig();
|
|
178
|
-
logger.error(
|
|
178
|
+
logger.error('No option provided. Use --init, --set, or --show');
|
|
179
179
|
}
|
|
180
180
|
catch (error) {
|
|
181
181
|
logger.error('Config operation failed:', error);
|
|
@@ -187,8 +187,8 @@ program
|
|
|
187
187
|
* Remove all generated SVG React components from an output folder.
|
|
188
188
|
*/
|
|
189
189
|
program
|
|
190
|
-
.command(
|
|
191
|
-
.description(
|
|
190
|
+
.command('clean <out>')
|
|
191
|
+
.description('Remove all generated SVG React components from output folder')
|
|
192
192
|
.action(async (args) => {
|
|
193
193
|
try {
|
|
194
194
|
const [out] = args;
|
package/dist/config.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import path from
|
|
2
|
-
import { FileSystem } from
|
|
3
|
-
const CONFIG_FILE =
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import { FileSystem } from './utils/native.js';
|
|
3
|
+
const CONFIG_FILE = '.svgconfig.json';
|
|
4
4
|
/**
|
|
5
5
|
* Get the absolute path to the configuration file.
|
|
6
6
|
*
|
|
@@ -31,24 +31,24 @@ export function writeConfig(config) {
|
|
|
31
31
|
*/
|
|
32
32
|
export async function initConfig() {
|
|
33
33
|
if (await FileSystem.exists(getConfigPath())) {
|
|
34
|
-
console.log(
|
|
34
|
+
console.log('⚠️ Config file already exists:', getConfigPath());
|
|
35
35
|
return;
|
|
36
36
|
}
|
|
37
37
|
const defaultConfig = {
|
|
38
|
-
source:
|
|
39
|
-
output:
|
|
38
|
+
source: './src/assets/svg',
|
|
39
|
+
output: './src/components/icons',
|
|
40
40
|
watch: false,
|
|
41
41
|
defaultWidth: 24,
|
|
42
42
|
defaultHeight: 24,
|
|
43
|
-
defaultFill:
|
|
43
|
+
defaultFill: 'currentColor',
|
|
44
44
|
exclude: [],
|
|
45
45
|
styleRules: {
|
|
46
|
-
fill:
|
|
47
|
-
stroke:
|
|
46
|
+
fill: 'inherit',
|
|
47
|
+
stroke: 'none',
|
|
48
48
|
},
|
|
49
49
|
};
|
|
50
50
|
writeConfig(defaultConfig);
|
|
51
|
-
console.log(
|
|
51
|
+
console.log('✅ Config file created:', getConfigPath());
|
|
52
52
|
}
|
|
53
53
|
/**
|
|
54
54
|
* Set a specific configuration key to a new value.
|
|
@@ -67,6 +67,6 @@ export function setConfig(key, value) {
|
|
|
67
67
|
*/
|
|
68
68
|
export function showConfig() {
|
|
69
69
|
const config = readConfig();
|
|
70
|
-
console.log(
|
|
70
|
+
console.log('📄 Current Config:');
|
|
71
71
|
console.log(JSON.stringify(config, null, 2));
|
|
72
72
|
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Enhanced error handling system with detailed error tracking and recovery
|
|
3
|
+
*/
|
|
4
|
+
export interface SVGError {
|
|
5
|
+
code: string;
|
|
6
|
+
message: string;
|
|
7
|
+
severity: 'low' | 'medium' | 'high' | 'critical';
|
|
8
|
+
context?: Record<string, any>;
|
|
9
|
+
timestamp: number;
|
|
10
|
+
stack?: string;
|
|
11
|
+
}
|
|
12
|
+
export interface ErrorRecoveryStrategy {
|
|
13
|
+
canRecover(error: SVGError): boolean;
|
|
14
|
+
recover(error: SVGError, context?: any): Promise<any>;
|
|
15
|
+
}
|
|
16
|
+
export declare class SVGErrorHandler {
|
|
17
|
+
private static instance;
|
|
18
|
+
private errorHistory;
|
|
19
|
+
private recoveryStrategies;
|
|
20
|
+
private readonly maxHistorySize;
|
|
21
|
+
private constructor();
|
|
22
|
+
static getInstance(): SVGErrorHandler;
|
|
23
|
+
/**
|
|
24
|
+
* Handle an error with context and attempted recovery
|
|
25
|
+
*/
|
|
26
|
+
handleError(error: Error | SVGError, context?: Record<string, any>): Promise<{
|
|
27
|
+
recovered: boolean;
|
|
28
|
+
result?: any;
|
|
29
|
+
}>;
|
|
30
|
+
/**
|
|
31
|
+
* Register a custom error recovery strategy
|
|
32
|
+
*/
|
|
33
|
+
registerRecoveryStrategy(errorCode: string, strategy: ErrorRecoveryStrategy): void;
|
|
34
|
+
/**
|
|
35
|
+
* Get error statistics
|
|
36
|
+
*/
|
|
37
|
+
getErrorStats(): {
|
|
38
|
+
total: number;
|
|
39
|
+
bySeverity: Record<string, number>;
|
|
40
|
+
byCode: Record<string, number>;
|
|
41
|
+
recentErrors: SVGError[];
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* Clear error history
|
|
45
|
+
*/
|
|
46
|
+
clearHistory(): void;
|
|
47
|
+
private normalizeError;
|
|
48
|
+
private categorizeError;
|
|
49
|
+
private determineSeverity;
|
|
50
|
+
private logError;
|
|
51
|
+
private addToHistory;
|
|
52
|
+
private attemptRecovery;
|
|
53
|
+
private setupDefaultStrategies;
|
|
54
|
+
}
|
|
55
|
+
export declare const errorHandler: SVGErrorHandler;
|
|
56
|
+
/**
|
|
57
|
+
* Utility function to wrap async operations with error handling
|
|
58
|
+
*/
|
|
59
|
+
export declare function withErrorHandling<T>(operation: () => Promise<T>, context?: Record<string, any>): Promise<T | null>;
|
|
60
|
+
/**
|
|
61
|
+
* Decorator for automatic error handling
|
|
62
|
+
*/
|
|
63
|
+
export declare function handleErrors(context?: Record<string, any>): (target: any, propertyName: string, descriptor: PropertyDescriptor) => void;
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
import { logger } from '../core/logger.js';
|
|
2
|
+
export class SVGErrorHandler {
|
|
3
|
+
static instance;
|
|
4
|
+
errorHistory = [];
|
|
5
|
+
recoveryStrategies = new Map();
|
|
6
|
+
maxHistorySize = 100;
|
|
7
|
+
constructor() {
|
|
8
|
+
this.setupDefaultStrategies();
|
|
9
|
+
}
|
|
10
|
+
static getInstance() {
|
|
11
|
+
if (!SVGErrorHandler.instance) {
|
|
12
|
+
SVGErrorHandler.instance = new SVGErrorHandler();
|
|
13
|
+
}
|
|
14
|
+
return SVGErrorHandler.instance;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Handle an error with context and attempted recovery
|
|
18
|
+
*/
|
|
19
|
+
async handleError(error, context) {
|
|
20
|
+
const svgError = this.normalizeError(error, context);
|
|
21
|
+
// Log error based on severity
|
|
22
|
+
this.logError(svgError);
|
|
23
|
+
// Add to history
|
|
24
|
+
this.addToHistory(svgError);
|
|
25
|
+
// Attempt recovery
|
|
26
|
+
const recoveryResult = await this.attemptRecovery(svgError, context);
|
|
27
|
+
return recoveryResult;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Register a custom error recovery strategy
|
|
31
|
+
*/
|
|
32
|
+
registerRecoveryStrategy(errorCode, strategy) {
|
|
33
|
+
this.recoveryStrategies.set(errorCode, strategy);
|
|
34
|
+
logger.debug(`Recovery strategy registered for error code: ${errorCode}`);
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Get error statistics
|
|
38
|
+
*/
|
|
39
|
+
getErrorStats() {
|
|
40
|
+
const bySeverity = {};
|
|
41
|
+
const byCode = {};
|
|
42
|
+
this.errorHistory.forEach(error => {
|
|
43
|
+
bySeverity[error.severity] = (bySeverity[error.severity] || 0) + 1;
|
|
44
|
+
byCode[error.code] = (byCode[error.code] || 0) + 1;
|
|
45
|
+
});
|
|
46
|
+
return {
|
|
47
|
+
total: this.errorHistory.length,
|
|
48
|
+
bySeverity,
|
|
49
|
+
byCode,
|
|
50
|
+
recentErrors: this.errorHistory.slice(-10),
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Clear error history
|
|
55
|
+
*/
|
|
56
|
+
clearHistory() {
|
|
57
|
+
this.errorHistory = [];
|
|
58
|
+
logger.debug('Error history cleared');
|
|
59
|
+
}
|
|
60
|
+
// Private methods
|
|
61
|
+
normalizeError(error, context) {
|
|
62
|
+
if ('code' in error && 'severity' in error) {
|
|
63
|
+
return error;
|
|
64
|
+
}
|
|
65
|
+
// Convert regular Error to SVGError
|
|
66
|
+
const regularError = error;
|
|
67
|
+
return {
|
|
68
|
+
code: this.categorizeError(regularError),
|
|
69
|
+
message: regularError.message,
|
|
70
|
+
severity: this.determineSeverity(regularError),
|
|
71
|
+
context: context || {},
|
|
72
|
+
timestamp: Date.now(),
|
|
73
|
+
stack: regularError.stack,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
categorizeError(error) {
|
|
77
|
+
const message = error.message.toLowerCase();
|
|
78
|
+
if (message.includes('file not found') || message.includes('enoent')) {
|
|
79
|
+
return 'FILE_NOT_FOUND';
|
|
80
|
+
}
|
|
81
|
+
if (message.includes('permission') || message.includes('eacces')) {
|
|
82
|
+
return 'PERMISSION_DENIED';
|
|
83
|
+
}
|
|
84
|
+
if (message.includes('parse') || message.includes('syntax')) {
|
|
85
|
+
return 'PARSE_ERROR';
|
|
86
|
+
}
|
|
87
|
+
if (message.includes('timeout')) {
|
|
88
|
+
return 'TIMEOUT_ERROR';
|
|
89
|
+
}
|
|
90
|
+
if (message.includes('network') || message.includes('connection')) {
|
|
91
|
+
return 'NETWORK_ERROR';
|
|
92
|
+
}
|
|
93
|
+
if (message.includes('svg') && message.includes('invalid')) {
|
|
94
|
+
return 'INVALID_SVG';
|
|
95
|
+
}
|
|
96
|
+
return 'UNKNOWN_ERROR';
|
|
97
|
+
}
|
|
98
|
+
determineSeverity(error) {
|
|
99
|
+
const message = error.message.toLowerCase();
|
|
100
|
+
if (message.includes('critical') || message.includes('fatal')) {
|
|
101
|
+
return 'critical';
|
|
102
|
+
}
|
|
103
|
+
if (message.includes('file not found') || message.includes('permission')) {
|
|
104
|
+
return 'high';
|
|
105
|
+
}
|
|
106
|
+
if (message.includes('parse') || message.includes('invalid')) {
|
|
107
|
+
return 'medium';
|
|
108
|
+
}
|
|
109
|
+
return 'low';
|
|
110
|
+
}
|
|
111
|
+
logError(error) {
|
|
112
|
+
const logMessage = `[${error.code}] ${error.message}`;
|
|
113
|
+
switch (error.severity) {
|
|
114
|
+
case 'critical':
|
|
115
|
+
logger.error('CRITICAL:', logMessage, error.context);
|
|
116
|
+
break;
|
|
117
|
+
case 'high':
|
|
118
|
+
logger.error('HIGH:', logMessage, error.context);
|
|
119
|
+
break;
|
|
120
|
+
case 'medium':
|
|
121
|
+
logger.warn('MEDIUM:', logMessage, error.context);
|
|
122
|
+
break;
|
|
123
|
+
case 'low':
|
|
124
|
+
logger.info('LOW:', logMessage, error.context);
|
|
125
|
+
break;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
addToHistory(error) {
|
|
129
|
+
this.errorHistory.push(error);
|
|
130
|
+
// Maintain history size limit
|
|
131
|
+
if (this.errorHistory.length > this.maxHistorySize) {
|
|
132
|
+
this.errorHistory = this.errorHistory.slice(-this.maxHistorySize);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
async attemptRecovery(error, context) {
|
|
136
|
+
const strategy = this.recoveryStrategies.get(error.code);
|
|
137
|
+
if (!strategy) {
|
|
138
|
+
logger.debug(`No recovery strategy found for error code: ${error.code}`);
|
|
139
|
+
return { recovered: false };
|
|
140
|
+
}
|
|
141
|
+
try {
|
|
142
|
+
if (!strategy.canRecover(error)) {
|
|
143
|
+
logger.debug(`Recovery strategy declined to handle error: ${error.code}`);
|
|
144
|
+
return { recovered: false };
|
|
145
|
+
}
|
|
146
|
+
logger.info(`Attempting recovery for error: ${error.code}`);
|
|
147
|
+
const result = await strategy.recover(error, context);
|
|
148
|
+
logger.success(`Successfully recovered from error: ${error.code}`);
|
|
149
|
+
return { recovered: true, result };
|
|
150
|
+
}
|
|
151
|
+
catch (recoveryError) {
|
|
152
|
+
logger.error(`Recovery failed for error ${error.code}:`, recoveryError);
|
|
153
|
+
return { recovered: false };
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
setupDefaultStrategies() {
|
|
157
|
+
// File not found recovery
|
|
158
|
+
this.registerRecoveryStrategy('FILE_NOT_FOUND', {
|
|
159
|
+
canRecover: error => error.context?.filePath && error.context?.canSkip === true,
|
|
160
|
+
recover: async (error, context) => {
|
|
161
|
+
logger.warn(`Skipping missing file: ${error.context?.filePath}`);
|
|
162
|
+
return { skipped: true, filePath: error.context?.filePath };
|
|
163
|
+
},
|
|
164
|
+
});
|
|
165
|
+
// Invalid SVG recovery
|
|
166
|
+
this.registerRecoveryStrategy('INVALID_SVG', {
|
|
167
|
+
canRecover: error => error.context?.svgContent,
|
|
168
|
+
recover: async (error, context) => {
|
|
169
|
+
logger.info('Attempting to clean invalid SVG content');
|
|
170
|
+
// Basic SVG cleanup
|
|
171
|
+
let cleaned = error.context?.svgContent || '';
|
|
172
|
+
// Remove potentially problematic content
|
|
173
|
+
cleaned = cleaned
|
|
174
|
+
.replace(/<script[\s\S]*?<\/script>/gi, '') // Remove scripts
|
|
175
|
+
.replace(/<style[\s\S]*?<\/style>/gi, '') // Remove styles
|
|
176
|
+
.replace(/on\w+="[^"]*"/gi, '') // Remove event handlers
|
|
177
|
+
.replace(/javascript:[^"']*/gi, ''); // Remove javascript: URLs
|
|
178
|
+
return { cleanedContent: cleaned };
|
|
179
|
+
},
|
|
180
|
+
});
|
|
181
|
+
// Permission denied recovery
|
|
182
|
+
this.registerRecoveryStrategy('PERMISSION_DENIED', {
|
|
183
|
+
canRecover: error => error.context?.alternative,
|
|
184
|
+
recover: async (error, context) => {
|
|
185
|
+
logger.warn(`Using alternative path due to permission issue: ${error.context?.alternative}`);
|
|
186
|
+
return { alternativePath: error.context?.alternative };
|
|
187
|
+
},
|
|
188
|
+
});
|
|
189
|
+
logger.debug('Default error recovery strategies loaded');
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
// Export singleton instance and utilities
|
|
193
|
+
export const errorHandler = SVGErrorHandler.getInstance();
|
|
194
|
+
/**
|
|
195
|
+
* Utility function to wrap async operations with error handling
|
|
196
|
+
*/
|
|
197
|
+
export async function withErrorHandling(operation, context) {
|
|
198
|
+
try {
|
|
199
|
+
return await operation();
|
|
200
|
+
}
|
|
201
|
+
catch (error) {
|
|
202
|
+
const result = await errorHandler.handleError(error, context);
|
|
203
|
+
if (result.recovered) {
|
|
204
|
+
return result.result;
|
|
205
|
+
}
|
|
206
|
+
// Re-throw if not recovered and severity is high
|
|
207
|
+
const svgError = error;
|
|
208
|
+
if (svgError.severity === 'high' || svgError.severity === 'critical') {
|
|
209
|
+
throw error;
|
|
210
|
+
}
|
|
211
|
+
return null;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Decorator for automatic error handling
|
|
216
|
+
*/
|
|
217
|
+
export function handleErrors(context) {
|
|
218
|
+
return function (target, propertyName, descriptor) {
|
|
219
|
+
const method = descriptor.value;
|
|
220
|
+
descriptor.value = async function (...args) {
|
|
221
|
+
return withErrorHandling(() => method.apply(this, args), {
|
|
222
|
+
method: propertyName,
|
|
223
|
+
...context,
|
|
224
|
+
});
|
|
225
|
+
};
|
|
226
|
+
};
|
|
227
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { ComponentGenerationOptions, FrameworkType } from '../types/index.js';
|
|
2
|
+
export type { FrameworkType, FrameworkOptions } from '../types/index.js';
|
|
3
|
+
export declare class FrameworkTemplateEngine {
|
|
4
|
+
generateComponent(options: ComponentGenerationOptions): string;
|
|
5
|
+
getFileExtension(framework: FrameworkType, typescript?: boolean): string;
|
|
6
|
+
private parseSVG;
|
|
7
|
+
private generateReactComponent;
|
|
8
|
+
private generateVueComponent;
|
|
9
|
+
private generateSvelteComponent;
|
|
10
|
+
private generateAngularComponent;
|
|
11
|
+
private generateSolidComponent;
|
|
12
|
+
private generatePreactComponent;
|
|
13
|
+
private generateLitComponent;
|
|
14
|
+
private generateVanillaComponent;
|
|
15
|
+
private toKebabCase;
|
|
16
|
+
}
|
|
17
|
+
export declare const frameworkTemplateEngine: FrameworkTemplateEngine;
|