@sun-asterisk/sunlint 1.1.3 → 1.1.4

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/.sunlint.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "extends": ["recommended"],
2
+ "extends": ["@sun/sunlint/recommended"],
3
3
  "rules": {
4
4
  "C019": "warn",
5
5
  "C006": "warn",
package/README.md CHANGED
@@ -8,29 +8,30 @@ Sun Lint is a universal coding standards checker providing comprehensive code qu
8
8
 
9
9
  ### **✨ Key Features**
10
10
  - ✅ **97+ Coding Rules**: Quality (30), Security (47), TypeScript-specific
11
- - ✅ **AST-Enhanced Analysis**: Superior accuracy with Babel/ESLint parsers
11
+ - ✅ **Built-in AST Analysis**: JavaScript/TypeScript parsing out of the box
12
12
  - ✅ **Multi-Engine Architecture**: Heuristic + ESLint + OpenAI integration
13
13
  - ✅ **Git Integration**: `--changed-files`, `--staged-files`, `--pr-mode`
14
14
  - ✅ **TypeScript Support**: Native TypeScript 5.8+ analysis
15
+ - ✅ **Zero Config**: Works immediately after `npm install`
15
16
  - ✅ **CI/CD Ready**: Baseline comparison, fail-on-new-violations
16
17
  - ✅ **Advanced File Targeting**: Include/exclude patterns, language filtering
17
18
 
18
19
  ### **🚀 Quick Start**
19
20
  ```bash
20
- # Install globally
21
+ # Install
21
22
  npm install -g @sun-asterisk/sunlint
22
23
 
23
- # Basic usage (uses config file or default patterns)
24
+ # Basic usage - works immediately!
24
25
  sunlint --all
25
26
  sunlint --rules=C019,C006
26
27
 
27
- # Explicit input specification
28
+ # With input specification
28
29
  sunlint --all --input=src
29
30
  sunlint --rules=C019,C006 --input=src
30
31
  sunlint --quality --input=src
31
32
  sunlint --security --input=src
32
33
 
33
- # ESLint integration (multi-engine analysis)
34
+ # ESLint integration (requires eslint dependency)
34
35
  sunlint --rules=C010,C006 --eslint-integration --input=src
35
36
 
36
37
  # Git integration
@@ -48,12 +49,66 @@ sunlint --version
48
49
  ### **Project Installation**
49
50
  ```bash
50
51
  npm install --save-dev @sun-asterisk/sunlint
52
+ ```
53
+
54
+ **✅ Works immediately** with JavaScript analysis using built-in AST parsers (`@babel/parser`, `espree`)
55
+
56
+ ### **Enhanced TypeScript Support**
57
+ For advanced TypeScript analysis with ESLint integration:
58
+
59
+ ```bash
60
+ npm install --save-dev @sun-asterisk/sunlint eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin typescript
61
+ ```
62
+
63
+ ### **What's Included by Default**
64
+ - ✅ **JavaScript Analysis**: High-accuracy AST analysis out of the box
65
+ - ✅ **Basic TypeScript**: Works with built-in Babel parser
66
+ - ✅ **97+ Rules**: All quality and security rules available
67
+ - ✅ **Heuristic Engine**: Pattern-based analysis for all languages
68
+
69
+ ### **Optional Dependencies (Install as needed)**
70
+ ```bash
71
+ # For ESLint engine integration
72
+ npm install eslint --save-dev
73
+
74
+ # For enhanced TypeScript analysis
75
+ npm install @typescript-eslint/parser @typescript-eslint/eslint-plugin --save-dev
76
+
77
+ # For TypeScript compiler integration
78
+ npm install typescript --save-dev
79
+ ```
80
+
81
+ **Quick setup for TypeScript projects:**
82
+ ```bash
83
+ npm install --save-dev @sun-asterisk/sunlint eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin typescript
84
+ ```
85
+
86
+ > 💡 **Note**: SunLint gracefully handles missing dependencies. Install only what your project needs. See [docs/DEPENDENCIES.md](docs/DEPENDENCIES.md) for detailed guidance.
51
87
 
52
88
  # Package.json scripts
89
+ ```json
53
90
  {
54
91
  "scripts": {
55
92
  "lint": "sunlint --all --input=src",
56
- "lint:changed": "sunlint --all --changed-files"
93
+ "lint:changed": "sunlint --all --changed-files",
94
+ "lint:typescript": "sunlint --all --input=src",
95
+ "lint:eslint-integration": "sunlint --all --eslint-integration --input=src"
96
+ },
97
+ "devDependencies": {
98
+ "@sun-asterisk/sunlint": "^1.2.0"
99
+ }
100
+ }
101
+ ```
102
+
103
+ **For TypeScript projects, add:**
104
+ ```json
105
+ {
106
+ "devDependencies": {
107
+ "@sun-asterisk/sunlint": "^1.2.0",
108
+ "eslint": "^8.50.0",
109
+ "@typescript-eslint/parser": "^7.2.0",
110
+ "@typescript-eslint/eslint-plugin": "^7.18.0",
111
+ "typescript": "^5.0.0"
57
112
  }
58
113
  }
59
114
  ```
@@ -209,16 +264,28 @@ Complete reference with all available options:
209
264
 
210
265
  ### **Development**
211
266
  ```bash
212
- # Run all rules
213
- sunlint --all --input=src
267
+ # Quick start - works immediately
268
+ npm install --save-dev @sun-asterisk/sunlint
269
+ npx sunlint --all --input=src
214
270
 
215
271
  # Check specific rules
216
272
  sunlint --rules=C019,S005 --input=src
217
273
 
218
- # ESLint + Git integration
274
+ # ESLint integration (requires eslint dependency)
275
+ npm install --save-dev eslint
219
276
  sunlint --all --eslint-integration --changed-files
220
277
  ```
221
278
 
279
+ ### **TypeScript Projects**
280
+ ```bash
281
+ # Enhanced TypeScript setup
282
+ npm install --save-dev @sun-asterisk/sunlint eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin typescript
283
+
284
+ # Full TypeScript analysis
285
+ sunlint --all --input=src
286
+ sunlint --all --eslint-integration --input=src
287
+ ```
288
+
222
289
  ### **CI/CD**
223
290
  ```bash
224
291
  # Full project scan
@@ -227,7 +294,7 @@ sunlint --all --input=. --format=json --output=report.json
227
294
  # PR validation
228
295
  sunlint --all --changed-files --fail-on-new-violations
229
296
 
230
- # Pre-commit hook
297
+ # Pre-commit hook
231
298
  sunlint --all --staged-files --format=summary
232
299
  ```
233
300
 
@@ -104,7 +104,7 @@
104
104
  "R001": ["react/no-this-in-sfc", "no-param-reassign", "react/function-component-definition", "react/forbid-component-props"],
105
105
  "R002": ["react-hooks/rules-of-hooks", "react-hooks/exhaustive-deps", "react/no-did-mount-set-state", "react/no-did-update-set-state"],
106
106
  "R003": ["react/no-direct-mutation-state", "react/jsx-no-constructed-context-values", "react/forbid-dom-props"],
107
- "R004": ["@typescript-eslint/prefer-readonly", "react/forbid-foreign-prop-types"],
107
+ "R004": ["no-param-reassign", "react/forbid-foreign-prop-types"],
108
108
  "R005": ["react/jsx-no-bind"],
109
109
  "R006": ["react/jsx-pascal-case", "react/jsx-uses-react", "react/jsx-uses-vars"],
110
110
  "R007": ["react-hooks/rules-of-hooks"],
@@ -651,13 +651,13 @@
651
651
  "quality": {
652
652
  "name": "Code Quality",
653
653
  "description": "Rules for code quality improvement",
654
- "rules": ["C002", "C003", "C006", "C010", "C013", "C014", "C017", "C018", "C019", "C023", "C027", "C029", "C030", "C031", "C034", "C035", "C041", "C042", "C043", "C047", "C048", "C076", "T002", "T003", "T004", "T007", "T011", "T019", "T025", "T026"],
654
+ "rules": ["C002", "C003", "C006", "C010", "C013", "C014", "C017", "C018", "C023", "C029", "C030", "C035", "C041", "C042", "C043", "C047", "C072", "C075", "C076", "T002", "T003", "T004", "T007", "T010", "T019", "T020", "T021", "R001", "R002", "R003", "R004", "R005", "R006"],
655
655
  "severity": "warning"
656
656
  },
657
657
  "security": {
658
658
  "name": "Security",
659
659
  "description": "Rules for security best practices",
660
- "rules": ["S003", "S005", "S006", "S008", "S009", "S010", "S011", "S012", "S014", "S015", "S016", "S017", "S018", "S019", "S020", "S022", "S023", "S025", "S026", "S027", "S029", "S030", "S033", "S034", "S035", "S036", "S037", "S038", "S039", "S041", "S042", "S043", "S044", "S045", "S046", "S047", "S048", "S050", "S052", "S054", "S055", "S057", "S058"],
660
+ "rules": ["S001", "S002", "S003", "S005", "S006", "S007", "S008", "S009", "S010", "S011", "S012", "S013", "S014", "S015", "S016", "S017", "S018", "S019", "S020", "S022", "S023", "S025", "S026", "S027", "S029", "S030", "S033", "S034", "S035", "S036", "S037", "S038", "S039", "S041", "S042", "S043", "S044", "S045", "S046", "S047", "S048", "S050", "S052", "S054", "S055", "S057", "S058"],
661
661
  "severity": "error"
662
662
  },
663
663
  "logging": {
@@ -745,11 +745,11 @@
745
745
  }
746
746
  },
747
747
  "metadata": {
748
- "version": "1.0.4",
749
- "lastUpdated": "2025-07-08",
748
+ "version": "1.1.4",
749
+ "lastUpdated": "2025-07-24",
750
750
  "totalRules": 44,
751
- "qualityRules": 4,
752
- "securityRules": 40,
751
+ "qualityRules": 33,
752
+ "securityRules": 47,
753
753
  "stableRules": 43,
754
754
  "experimentalRules": 1,
755
755
  "supportedLanguages": 4,
@@ -757,7 +757,8 @@
757
757
  "Security rules integration",
758
758
  "Category-based rule filtering",
759
759
  "Dynamic rule configuration",
760
- "ESLint integration enhancement"
760
+ "ESLint integration enhancement",
761
+ "React rules integration"
761
762
  ]
762
763
  }
763
764
  }
@@ -1,25 +1,31 @@
1
1
  /**
2
2
  * ESLint-based JavaScript Parser
3
3
  * Uses the same AST infrastructure as ESLint for reliable parsing
4
+ * Gracefully handles missing peer dependencies
4
5
  */
5
6
 
6
7
  class ESLintJavaScriptParser {
7
8
  constructor() {
8
9
  this.parser = null;
10
+ this.parserType = null;
9
11
  this.initParser();
10
12
  }
11
13
 
12
14
  initParser() {
13
- try {
14
- // Try to use @babel/parser (what ESLint uses internally)
15
- this.parser = require('@babel/parser');
16
- } catch (e1) {
15
+ // Try to dynamically load available parsers
16
+ const parsers = [
17
+ { name: '@babel/parser', type: 'babel' },
18
+ { name: 'espree', type: 'espree' }
19
+ ];
20
+
21
+ for (const { name, type } of parsers) {
17
22
  try {
18
- // Fallback to espree (ESLint's default parser)
19
- this.parser = require('espree');
20
- } catch (e2) {
21
- // If no parser available, this will be null
22
- this.parser = null;
23
+ this.parser = require(name);
24
+ this.parserType = type;
25
+ break;
26
+ } catch (error) {
27
+ // Continue to next parser
28
+ continue;
23
29
  }
24
30
  }
25
31
  }
@@ -28,11 +34,9 @@ class ESLintJavaScriptParser {
28
34
  if (!this.parser) return null;
29
35
 
30
36
  try {
31
- if (this.parser.parse) {
32
- // @babel/parser or espree
37
+ if (this.parserType === 'babel') {
33
38
  return this.parser.parse(code, {
34
- ecmaVersion: 'latest',
35
- sourceType: 'module',
39
+ sourceType: 'unambiguous',
36
40
  allowImportExportEverywhere: true,
37
41
  allowReturnOutsideFunction: true,
38
42
  plugins: [
@@ -43,14 +47,16 @@ class ESLintJavaScriptParser {
43
47
  'objectRestSpread',
44
48
  'optionalChaining',
45
49
  'nullishCoalescingOperator'
46
- ].filter(plugin => {
47
- // Only include plugins that are supported
48
- try {
49
- return true;
50
- } catch {
51
- return false;
52
- }
53
- })
50
+ ]
51
+ });
52
+ } else if (this.parserType === 'espree') {
53
+ return this.parser.parse(code, {
54
+ ecmaVersion: 'latest',
55
+ sourceType: 'module',
56
+ ecmaFeatures: {
57
+ jsx: true,
58
+ globalReturn: true
59
+ }
54
60
  });
55
61
  }
56
62
  } catch (error) {
@@ -1,26 +1,31 @@
1
1
  /**
2
2
  * ESLint-based TypeScript Parser
3
3
  * Uses @typescript-eslint/parser for TypeScript AST analysis
4
+ * Gracefully handles missing peer dependencies
4
5
  */
5
6
 
6
7
  class ESLintTypeScriptParser {
7
8
  constructor() {
8
9
  this.parser = null;
10
+ this.parserType = null;
9
11
  this.initParser();
10
12
  }
11
13
 
12
14
  initParser() {
13
- try {
14
- // Try to use @typescript-eslint/parser
15
- this.parser = require('@typescript-eslint/parser');
16
- } catch (e1) {
15
+ // Try to dynamically load available TypeScript parsers
16
+ const parsers = [
17
+ { name: '@typescript-eslint/parser', type: 'typescript-eslint' },
18
+ { name: '@babel/parser', type: 'babel' }
19
+ ];
20
+
21
+ for (const { name, type } of parsers) {
17
22
  try {
18
- // Fallback to @babel/parser with TypeScript plugin
19
- this.parser = require('@babel/parser');
20
- this.parserType = 'babel';
21
- } catch (e2) {
22
- // If no parser available, this will be null
23
- this.parser = null;
23
+ this.parser = require(name);
24
+ this.parserType = type;
25
+ break;
26
+ } catch (error) {
27
+ // Continue to next parser
28
+ continue;
24
29
  }
25
30
  }
26
31
  }
@@ -29,45 +34,32 @@ class ESLintTypeScriptParser {
29
34
  if (!this.parser) return null;
30
35
 
31
36
  try {
32
- // Try Babel parser first for better TypeScript 5.x support
33
37
  if (this.parserType === 'babel') {
34
38
  return this.parser.parse(code, {
35
- sourceType: 'module',
39
+ sourceType: 'unambiguous',
36
40
  allowImportExportEverywhere: true,
37
41
  plugins: ['typescript', 'jsx', 'decorators-legacy']
38
42
  });
39
- } else {
40
- // Use Babel parser as primary for TypeScript files
43
+ } else if (this.parserType === 'typescript-eslint') {
44
+ // First try @babel/parser for better compatibility
41
45
  try {
42
46
  const babel = require('@babel/parser');
43
47
  return babel.parse(code, {
44
- sourceType: 'module',
48
+ sourceType: 'unambiguous',
45
49
  allowImportExportEverywhere: true,
46
50
  plugins: ['typescript', 'jsx', 'decorators-legacy', 'classProperties']
47
51
  });
48
52
  } catch (babelError) {
49
- // Fallback to @typescript-eslint/parser (with warnings suppressed)
53
+ // Fallback to @typescript-eslint/parser if available
50
54
  if (this.parser.parseForESLint) {
51
- const originalWarn = console.warn;
52
- const originalError = console.error;
53
- console.warn = () => {}; // Suppress warnings temporarily
54
- console.error = () => {}; // Suppress errors temporarily
55
-
56
- try {
57
- const result = this.parser.parseForESLint(code, {
58
- ecmaVersion: 'latest',
59
- sourceType: 'module',
60
- ecmaFeatures: {
61
- jsx: true
62
- },
63
- errorOnUnknownASTType: false // Don't error on unknown AST types
64
- });
65
- return result.ast;
66
- } finally {
67
- // Always restore console methods
68
- console.warn = originalWarn;
69
- console.error = originalError;
70
- }
55
+ const result = this.parser.parseForESLint(code, {
56
+ ecmaVersion: 'latest',
57
+ sourceType: 'module',
58
+ ecmaFeatures: {
59
+ jsx: true
60
+ }
61
+ });
62
+ return result.ast;
71
63
  }
72
64
  }
73
65
  }
@@ -0,0 +1,125 @@
1
+ /**
2
+ * Dependency Checker
3
+ * Checks for optional peer dependencies and provides helpful messages
4
+ */
5
+
6
+ class DependencyChecker {
7
+ constructor() {
8
+ this.checkedDependencies = new Set();
9
+ }
10
+
11
+ /**
12
+ * Check if a dependency is available
13
+ */
14
+ isDependencyAvailable(packageName) {
15
+ try {
16
+ require.resolve(packageName);
17
+ return true;
18
+ } catch (error) {
19
+ return false;
20
+ }
21
+ }
22
+
23
+ /**
24
+ * Check for ESLint engine dependencies
25
+ */
26
+ checkESLintDependencies() {
27
+ const dependencies = {
28
+ 'eslint': { required: false, description: 'ESLint engine support' },
29
+ '@typescript-eslint/eslint-plugin': { required: false, description: 'TypeScript ESLint rules' },
30
+ '@typescript-eslint/parser': { required: false, description: 'TypeScript ESLint parsing' },
31
+ 'typescript': { required: false, description: 'TypeScript compiler' }
32
+ };
33
+
34
+ const missing = [];
35
+ const available = [];
36
+
37
+ for (const [pkg, info] of Object.entries(dependencies)) {
38
+ if (this.isDependencyAvailable(pkg)) {
39
+ available.push(pkg);
40
+ } else {
41
+ missing.push({ pkg, ...info });
42
+ }
43
+ }
44
+
45
+ return { available, missing };
46
+ }
47
+
48
+ /**
49
+ * Check for AST parsing dependencies
50
+ */
51
+ checkASTDependencies() {
52
+ const dependencies = {
53
+ '@babel/parser': { required: false, description: 'JavaScript AST parsing' },
54
+ 'espree': { required: false, description: 'ECMAScript AST parsing' }
55
+ };
56
+
57
+ const missing = [];
58
+ const available = [];
59
+
60
+ for (const [pkg, info] of Object.entries(dependencies)) {
61
+ if (this.isDependencyAvailable(pkg)) {
62
+ available.push(pkg);
63
+ } else {
64
+ missing.push({ pkg, ...info });
65
+ }
66
+ }
67
+
68
+ return { available, missing };
69
+ }
70
+
71
+ /**
72
+ * Show installation instructions for missing dependencies
73
+ */
74
+ showInstallationInstructions(missing, context = 'general') {
75
+ if (missing.length === 0) return;
76
+
77
+ console.log('\n📦 Optional dependencies not found:');
78
+
79
+ for (const { pkg, description } of missing) {
80
+ console.log(` • ${pkg} - ${description}`);
81
+ }
82
+
83
+ const packages = missing.map(m => m.pkg).join(' ');
84
+
85
+ if (context === 'eslint') {
86
+ console.log('\n💡 To enable ESLint engine features, install:');
87
+ console.log(` npm install ${packages}`);
88
+ console.log('\n Or add to your project dependencies if you already have them.');
89
+ } else if (context === 'ast') {
90
+ console.log('\n💡 To enable AST analysis features, install:');
91
+ console.log(` npm install ${packages}`);
92
+ } else {
93
+ console.log('\n💡 To enable full functionality, install:');
94
+ console.log(` npm install ${packages}`);
95
+ }
96
+
97
+ console.log('\n SunLint will continue using heuristic analysis.\n');
98
+ }
99
+
100
+ /**
101
+ * Check and notify about missing dependencies (only once per session)
102
+ */
103
+ checkAndNotify(type = 'all') {
104
+ const key = `checked_${type}`;
105
+ if (this.checkedDependencies.has(key)) return;
106
+
107
+ this.checkedDependencies.add(key);
108
+
109
+ if (type === 'eslint' || type === 'all') {
110
+ const { missing } = this.checkESLintDependencies();
111
+ if (missing.length > 0) {
112
+ this.showInstallationInstructions(missing, 'eslint');
113
+ }
114
+ }
115
+
116
+ if (type === 'ast' || type === 'all') {
117
+ const { missing } = this.checkASTDependencies();
118
+ if (missing.length > 0) {
119
+ this.showInstallationInstructions(missing, 'ast');
120
+ }
121
+ }
122
+ }
123
+ }
124
+
125
+ module.exports = new DependencyChecker();
@@ -0,0 +1,164 @@
1
+ /**
2
+ * Smart Dependency Auto-Installer
3
+ * Automatically installs missing peer dependencies when SunLint runs
4
+ * Future: Will support package flavor recommendations
5
+ */
6
+
7
+ const { execSync } = require('child_process');
8
+ const fs = require('fs');
9
+ const path = require('path');
10
+
11
+ class SmartInstaller {
12
+ constructor() {
13
+ this.installedInSession = new Set();
14
+ this.packageFlavors = {
15
+ 'typescript': '@sun-asterisk/sunlint-typescript',
16
+ 'dart': '@sun-asterisk/sunlint-dart',
17
+ 'python': '@sun-asterisk/sunlint-python',
18
+ 'go': '@sun-asterisk/sunlint-go',
19
+ 'full': '@sun-asterisk/sunlint-full'
20
+ };
21
+ }
22
+
23
+ /**
24
+ * Detect project type and recommend appropriate packages
25
+ */
26
+ detectProjectType(projectRoot) {
27
+ const packageJsonPath = path.join(projectRoot, 'package.json');
28
+ if (!fs.existsSync(packageJsonPath)) return ['basic'];
29
+
30
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
31
+ const types = [];
32
+
33
+ // Check for TypeScript
34
+ if (packageJson.devDependencies?.typescript ||
35
+ packageJson.dependencies?.typescript ||
36
+ fs.existsSync(path.join(projectRoot, 'tsconfig.json'))) {
37
+ types.push('typescript');
38
+ }
39
+
40
+ // Check for other languages (future)
41
+ if (fs.existsSync(path.join(projectRoot, 'pubspec.yaml'))) {
42
+ types.push('dart');
43
+ }
44
+
45
+ if (fs.existsSync(path.join(projectRoot, 'requirements.txt')) ||
46
+ fs.existsSync(path.join(projectRoot, 'pyproject.toml'))) {
47
+ types.push('python');
48
+ }
49
+
50
+ if (fs.existsSync(path.join(projectRoot, 'go.mod'))) {
51
+ types.push('go');
52
+ }
53
+
54
+ return types.length > 0 ? types : ['basic'];
55
+ }
56
+
57
+ /**
58
+ * Recommend optimal package flavors instead of individual dependencies
59
+ */
60
+ recommendPackageFlavors(missingDeps, projectTypes) {
61
+ const recommendations = [];
62
+
63
+ // If missing TypeScript deps and it's a TS project
64
+ if (missingDeps.some(d => d.pkg.includes('@typescript-eslint')) &&
65
+ projectTypes.includes('typescript')) {
66
+ recommendations.push({
67
+ package: '@sun-asterisk/sunlint-typescript',
68
+ reason: 'Complete TypeScript analysis support',
69
+ replaces: missingDeps.filter(d => d.pkg.includes('typescript')).map(d => d.pkg)
70
+ });
71
+ }
72
+
73
+ // If missing many ESLint deps, suggest full package
74
+ if (missingDeps.length >= 3 && missingDeps.some(d => d.pkg === 'eslint')) {
75
+ recommendations.push({
76
+ package: '@sun-asterisk/sunlint-full',
77
+ reason: 'Complete ESLint integration with all features',
78
+ replaces: missingDeps.map(d => d.pkg)
79
+ });
80
+ }
81
+
82
+ return recommendations;
83
+ }
84
+
85
+ /**
86
+ * Check if we're in a project that can install dependencies
87
+ */
88
+ canAutoInstall() {
89
+ // Check if package.json exists in current or parent directories
90
+ let currentDir = process.cwd();
91
+ const root = path.parse(currentDir).root;
92
+
93
+ while (currentDir !== root) {
94
+ if (fs.existsSync(path.join(currentDir, 'package.json'))) {
95
+ return currentDir;
96
+ }
97
+ currentDir = path.dirname(currentDir);
98
+ }
99
+ return null;
100
+ }
101
+
102
+ /**
103
+ * Auto-install missing dependencies with user confirmation
104
+ */
105
+ async autoInstallMissing(missingDeps, context = 'analysis') {
106
+ const projectRoot = this.canAutoInstall();
107
+ if (!projectRoot) {
108
+ this.showManualInstallInstructions(missingDeps);
109
+ return false;
110
+ }
111
+
112
+ console.log(`\n🔍 SunLint needs these dependencies for enhanced ${context}:`);
113
+ missingDeps.forEach(dep => console.log(` • ${dep.pkg} - ${dep.description}`));
114
+
115
+ const packages = missingDeps.map(d => d.pkg).join(' ');
116
+
117
+ console.log(`\n💡 Install command:`);
118
+ console.log(` npm install ${packages} --save-dev`);
119
+
120
+ // In CI environments, don't auto-install but show clear message
121
+ if (process.env.CI || process.env.NODE_ENV === 'test') {
122
+ console.log('\n⚠️ CI Environment: Add dependencies to package.json for consistent builds');
123
+ console.log(' SunLint will continue with available features\n');
124
+ return false;
125
+ }
126
+
127
+ // Interactive prompt for auto-install
128
+ const shouldAutoInstall = process.env.SUNLINT_AUTO_INSTALL === 'true';
129
+
130
+ if (shouldAutoInstall) {
131
+ try {
132
+ console.log('\n📦 Auto-installing dependencies...');
133
+ execSync(`npm install ${packages} --save-dev`, {
134
+ cwd: projectRoot,
135
+ stdio: 'pipe' // Less noisy
136
+ });
137
+ console.log('✅ Dependencies installed successfully!');
138
+ console.log('🔄 Re-running analysis with full features...\n');
139
+ return true;
140
+ } catch (error) {
141
+ console.log('❌ Auto-install failed, continuing with available features');
142
+ return false;
143
+ }
144
+ } else {
145
+ console.log('\n🔄 Continuing with available features...');
146
+ console.log('💡 Set SUNLINT_AUTO_INSTALL=true to enable automatic installation\n');
147
+ }
148
+
149
+ return false;
150
+ }
151
+
152
+ /**
153
+ * Show manual installation instructions
154
+ */
155
+ showManualInstallInstructions(missingDeps) {
156
+ console.log('\n📦 To enable full functionality, install:');
157
+ const packages = missingDeps.map(d => d.pkg).join(' ');
158
+ console.log(` npm install ${packages} --save-dev`);
159
+ console.log('\n💡 Or set SUNLINT_AUTO_INSTALL=true for automatic installation');
160
+ console.log(' SunLint will continue with heuristic analysis.\n');
161
+ }
162
+ }
163
+
164
+ module.exports = new SmartInstaller();
@@ -0,0 +1,90 @@
1
+ # Installing SunLint Dependencies
2
+
3
+ SunLint is designed to work immediately after installation with built-in JavaScript/TypeScript analysis capabilities. Additional dependencies are only needed for enhanced features.
4
+
5
+ ## Core Installation
6
+
7
+ ```bash
8
+ npm install @sun-asterisk/sunlint --save-dev
9
+ ```
10
+
11
+ **✅ What you get immediately:**
12
+ - High-accuracy JavaScript analysis (AST-based)
13
+ - Basic TypeScript analysis (Babel parser)
14
+ - All 97+ quality and security rules
15
+ - Heuristic analysis for all supported languages
16
+
17
+ ## Enhanced Features
18
+
19
+ ### For ESLint Integration
20
+
21
+ If you want to combine SunLint with ESLint rules and ecosystem:
22
+
23
+ ```bash
24
+ npm install eslint --save-dev
25
+ ```
26
+
27
+ ### For Advanced TypeScript Analysis
28
+
29
+ For enhanced TypeScript parsing and ESLint TypeScript rules:
30
+
31
+ ```bash
32
+ npm install @typescript-eslint/eslint-plugin @typescript-eslint/parser --save-dev
33
+ ```
34
+
35
+ ### For TypeScript Projects (Complete Setup)
36
+
37
+ For full TypeScript development support:
38
+
39
+ ```bash
40
+ npm install eslint typescript @typescript-eslint/eslint-plugin @typescript-eslint/parser --save-dev
41
+ ```
42
+
43
+ ## Installation Examples
44
+
45
+ ### Minimal Setup (JavaScript projects)
46
+ ```bash
47
+ npm install @sun-asterisk/sunlint --save-dev
48
+ npx sunlint --all --input=src # ✅ Works immediately
49
+ ```
50
+
51
+ ### TypeScript Projects
52
+ ```bash
53
+ npm install @sun-asterisk/sunlint eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin typescript --save-dev
54
+ npx sunlint --all --input=src # ✅ Full TypeScript support
55
+ ```
56
+
57
+ ### ESLint Integration
58
+ ```bash
59
+ npm install @sun-asterisk/sunlint eslint --save-dev
60
+ npx sunlint --all --eslint-integration --input=src # ✅ Combined analysis
61
+ ```
62
+
63
+ ## What happens without optional dependencies?
64
+
65
+ - **Without ESLint**: SunLint uses heuristic engine only (still very capable)
66
+ - **Without TypeScript parsers**: Falls back to Babel parser (good coverage)
67
+ - **Without TypeScript compiler**: Basic type checking only
68
+
69
+ **SunLint always provides analysis results** - dependencies only enhance capabilities.
70
+
71
+ ## Built-in vs Optional Parsers
72
+
73
+ ### ✅ Built-in (Always Available)
74
+ - **@babel/parser**: JavaScript + basic TypeScript support
75
+ - **espree**: ECMAScript parsing for compatibility
76
+
77
+ ### 🔄 Optional (Install as needed)
78
+ - **@typescript-eslint/parser**: Advanced TypeScript features
79
+ - **@typescript-eslint/eslint-plugin**: TypeScript-specific rules
80
+ - **eslint**: ESLint engine integration
81
+ - **typescript**: TypeScript compiler integration
82
+
83
+ ## Dependency Check
84
+
85
+ Run any SunLint command to see recommendations for your project:
86
+
87
+ ```bash
88
+ npx sunlint --help
89
+ # Automatically detects project type and suggests relevant dependencies
90
+ ```
@@ -0,0 +1,83 @@
1
+ # Future SunLint Package Strategy
2
+
3
+ ## Core Packages
4
+
5
+ ### @sun-asterisk/sunlint (Core)
6
+ - Size: ~235KB
7
+ - Features: Basic JS/TS heuristic analysis
8
+ - Dependencies: @babel/parser, espree
9
+ - Target: Minimal setup, basic quality checks
10
+
11
+ ### @sun-asterisk/sunlint-typescript
12
+ - Size: ~2MB
13
+ - Features: Full TypeScript analysis with AST
14
+ - Dependencies: Core + @typescript-eslint/parser, typescript
15
+ - Target: TypeScript projects
16
+
17
+ ### @sun-asterisk/sunlint-full
18
+ - Size: ~10MB
19
+ - Features: Complete ESLint integration, all parsers
20
+ - Dependencies: Core + all ESLint ecosystem
21
+ - Target: Full-featured analysis
22
+
23
+ ## Language Extensions
24
+
25
+ ### @sun-asterisk/sunlint-dart
26
+ - Dart-specific rules and analysis
27
+ - Dependencies: dart_analyzer, dart tools
28
+
29
+ ### @sun-asterisk/sunlint-python
30
+ - Python-specific rules
31
+ - Dependencies: pylint, autopep8, mypy
32
+
33
+ ### @sun-asterisk/sunlint-go
34
+ - Go-specific analysis
35
+ - Dependencies: staticcheck, golint
36
+
37
+ ## Feature Extensions
38
+
39
+ ### @sun-asterisk/sunlint-ai
40
+ - AI-powered code analysis
41
+ - Dependencies: OpenAI API, Claude API
42
+
43
+ ### @sun-asterisk/sunlint-security
44
+ - Advanced security scanning
45
+ - Dependencies: semgrep, snyk, security plugins
46
+
47
+ ## Installation Examples
48
+
49
+ ```bash
50
+ # Basic usage
51
+ npm install @sun-asterisk/sunlint --save-dev
52
+
53
+ # TypeScript project
54
+ npm install @sun-asterisk/sunlint-typescript --save-dev
55
+
56
+ # Multi-language project
57
+ npm install @sun-asterisk/sunlint @sun-asterisk/sunlint-dart @sun-asterisk/sunlint-python --save-dev
58
+
59
+ # Enterprise setup with all features
60
+ npm install @sun-asterisk/sunlint-full @sun-asterisk/sunlint-ai @sun-asterisk/sunlint-security --save-dev
61
+ ```
62
+
63
+ ## Configuration
64
+
65
+ ### Package-based auto-detection
66
+ ```json
67
+ // .sunlint.json
68
+ {
69
+ "extends": ["auto-detect-packages"], // Automatically use installed packages
70
+ "rules": {
71
+ "C010": "error"
72
+ }
73
+ }
74
+ ```
75
+
76
+ ### Smart recommendations
77
+ ```bash
78
+ # When SunLint detects TypeScript files but no TS package
79
+ npx sunlint --all
80
+ # Output:
81
+ # 💡 TypeScript files detected. For better analysis:
82
+ # npm install @sun-asterisk/sunlint-typescript --save-dev
83
+ ```
@@ -0,0 +1,112 @@
1
+ # Production Deployment Analysis - SunLint Size Impact
2
+
3
+ ## 🔍 **Câu hỏi từ Developer:**
4
+ *"Công việc trên có phải là phổ biến không, tức là khi deploy thông thường có làm các công việc đó không?"*
5
+
6
+ ## 📊 **Thực tế Deployment Phổ Biến**
7
+
8
+ ### ✅ **THỰC TẾ 1: DevDependencies tự động bị loại trừ**
9
+
10
+ **Hầu hết deployment platforms tự động loại trừ devDependencies:**
11
+
12
+ | Platform | Auto-exclude devDependencies | Command |
13
+ |----------|------------------------------|---------|
14
+ | **Heroku** | ✅ | `npm install --production` |
15
+ | **Vercel** | ✅ | `npm ci --production` |
16
+ | **Netlify** | ✅ | `npm install --production` |
17
+ | **Docker** | ✅ | `RUN npm ci --only=production` |
18
+ | **AWS Lambda** | ✅ | `npm install --production` |
19
+ | **Google Cloud** | ✅ | `npm ci --production` |
20
+
21
+ ### ✅ **THỰC TẾ 2: Build process tự nhiên**
22
+
23
+ **Typical CI/CD pipeline:**
24
+ ```bash
25
+ # Development
26
+ npm install # Cài tất cả (bao gồm SunLint)
27
+ npm run lint # SunLint chạy để check code
28
+ npm run test # Tests chạy
29
+ npm run build # Build production bundle
30
+
31
+ # Production deployment
32
+ npm ci --production # CHỈ cài runtime dependencies
33
+ # SunLint tự động bị loại trừ!
34
+ ```
35
+
36
+ ### ✅ **THỰC TẾ 3: Docker multistage builds**
37
+
38
+ **Phổ biến nhất - Docker multistage:**
39
+ ```dockerfile
40
+ # Build stage
41
+ FROM node:18 AS builder
42
+ COPY package*.json ./
43
+ RUN npm install # Cài tất cả, kể cả SunLint
44
+ COPY . .
45
+ RUN npm run build # SunLint chạy trong quá trình build
46
+
47
+ # Production stage
48
+ FROM node:18-alpine AS production
49
+ COPY package*.json ./
50
+ RUN npm ci --production --silent # CHỈ runtime deps
51
+ COPY --from=builder /app/dist ./dist
52
+ # SunLint không có trong production image!
53
+ ```
54
+
55
+ ## 🎯 **Kết luận về SunLint**
56
+
57
+ ### **TẠI SAO SUNLINT AN TOÀN 100%:**
58
+
59
+ 1. **DevDependency by design** - SunLint được thiết kế như linting tool
60
+ 2. **Industry standard** - Tất cả linting tools đều hoạt động như vậy
61
+ 3. **Automatic exclusion** - Deployment platforms tự động loại trừ
62
+ 4. **Zero production footprint** - Không code SunLint nào trong runtime
63
+
64
+ ### **SO SÁNH VỚI CÔNG CỤ KHÁC:**
65
+
66
+ | Tool | Size | Production Impact | Usage Pattern |
67
+ |------|------|-------------------|---------------|
68
+ | **ESLint** | ~500KB | ❌ (nếu sai cách) | DevDependency ✅ |
69
+ | **SunLint** | **241KB** | ✅ **KHÔNG** | DevDependency ✅ |
70
+ | **Prettier** | ~300KB | ❌ (nếu sai cách) | DevDependency ✅ |
71
+ | **TypeScript** | ~60MB | ❌ (nếu sai cách) | DevDependency ✅ |
72
+
73
+ ## 📈 **Best Practices Verification**
74
+
75
+ ### **✅ ĐÚNG CÁCH (99% cases):**
76
+ ```json
77
+ {
78
+ "devDependencies": {
79
+ "@sun-asterisk/sunlint": "^1.1.4",
80
+ "eslint": "^8.57.1",
81
+ "prettier": "^3.0.0"
82
+ },
83
+ "dependencies": {
84
+ "express": "^4.18.0" // Chỉ runtime deps
85
+ }
86
+ }
87
+ ```
88
+
89
+ ### **❌ SAI CÁCH (hiếm, chỉ newbie):**
90
+ ```json
91
+ {
92
+ "dependencies": {
93
+ "@sun-asterisk/sunlint": "^1.1.4", // ❌ Sai!
94
+ "express": "^4.18.0"
95
+ }
96
+ }
97
+ ```
98
+
99
+ ## 🚀 **Tóm tắt**
100
+
101
+ **CÂU TRẢ LỜI:** Các công việc này **HOÀN TOÀN PHỔ BIẾN** và **TỰ ĐỘNG** trong production deployment:
102
+
103
+ 1. ✅ **DevDependencies tự động bị loại trừ** - Industry standard
104
+ 2. ✅ **Build tools chỉ chạy development time** - Normal practice
105
+ 3. ✅ **Production chỉ có runtime code** - Security best practice
106
+ 4. ✅ **SunLint = 0KB trong production** - Guaranteed
107
+
108
+ **Developer không cần lo lắng về size impact của SunLint!**
109
+
110
+ ---
111
+ *Generated on: 2025-07-24*
112
+ *SunLint Version: 1.1.4*
@@ -0,0 +1,183 @@
1
+ # 📦 SunLint Production Size Impact Analysis
2
+
3
+ ## Tóm tắt cho Leadership
4
+
5
+ **KẾT LUẬN: SunLint KHÔNG làm tăng size production khi sử dụng đúng cách.**
6
+
7
+ ## Chi tiết phân tích
8
+
9
+ ### 1. Package Size của SunLint
10
+
11
+ ```bash
12
+ SunLint package size: 241.6 kB
13
+ SunLint unpacked size: 1.1 MB
14
+ Total files: 214
15
+ ```
16
+
17
+ ### 2. Test Production Impact
18
+
19
+ Chúng tôi đã tạo một project test để kiểm tra impact thực tế:
20
+
21
+ | Giai đoạn | Size | Ghi chú |
22
+ |-----------|------|---------|
23
+ | Project ban đầu | 8.0K | Chỉ có package.json và .gitignore |
24
+ | Sau khi cài SunLint (devDependency) | 88M | Bao gồm tất cả devDependencies |
25
+ | Production bundle (dist/) | 4.0K | Code production thực tế |
26
+ | Sau npm prune --production | 156K | Đã xóa tất cả devDependencies |
27
+
28
+ ### 3. Khuyến nghị sử dụng trong Production
29
+
30
+ #### ✅ ĐÚNG CÁCH (Production-friendly):
31
+
32
+ ```json
33
+ {
34
+ "devDependencies": {
35
+ "@sun-asterisk/sunlint": "^1.1.4"
36
+ }
37
+ }
38
+ ```
39
+
40
+ **Lợi ích:**
41
+ - ✅ Không ảnh hưởng size production bundle
42
+ - ✅ Chỉ cài khi development (`npm install`)
43
+ - ✅ Tự động loại trừ khỏi production (`npm prune --production`)
44
+ - ✅ CI/CD có thể dùng để check code quality
45
+
46
+ #### ❌ SAI CÁCH (Không khuyến nghị):
47
+
48
+ ```json
49
+ {
50
+ "dependencies": {
51
+ "@sun-asterisk/sunlint": "^1.1.4"
52
+ }
53
+ }
54
+ ```
55
+
56
+ **Vấn đề:**
57
+ - ❌ Tăng 1.1MB cho production bundle
58
+ - ❌ Không cần thiết cho runtime
59
+ - ❌ Làm chậm deployment
60
+
61
+ ### 4. Deployment Strategies
62
+
63
+ #### Option 1: Development Only (Khuyến nghị)
64
+ ```bash
65
+ # Development
66
+ npm install
67
+
68
+ # Production build
69
+ npm run build
70
+ npm prune --production
71
+ # → SunLint sẽ bị xóa hoàn toàn
72
+ ```
73
+
74
+ #### Option 2: CI/CD Pipeline
75
+ ```yaml
76
+ # .github/workflows/ci.yml
77
+ - name: Install deps
78
+ run: npm ci
79
+ - name: Run SunLint
80
+ run: npx sunlint --quality --input=src
81
+ - name: Build production
82
+ run: npm run build
83
+ - name: Remove dev deps
84
+ run: npm prune --production
85
+ ```
86
+
87
+ #### Option 3: Docker Multi-stage
88
+ ```dockerfile
89
+ # Development stage với SunLint
90
+ FROM node:18 as dev
91
+ COPY package*.json ./
92
+ RUN npm ci
93
+ COPY . .
94
+ RUN npx sunlint --all --input=src
95
+
96
+ # Production stage KHÔNG có SunLint
97
+ FROM node:18-alpine as prod
98
+ COPY package*.json ./
99
+ RUN npm ci --only=production
100
+ COPY dist/ ./dist/
101
+ ```
102
+
103
+ ### 5. So sánh với các tools khác
104
+
105
+ | Tool | Package Size | Production Impact | Use Case |
106
+ |------|-------------|-------------------|-----------|
107
+ | ESLint | ~500KB | ❌ Nếu để dependencies | Development only |
108
+ | Prettier | ~200KB | ❌ Nếu để dependencies | Development only |
109
+ | **SunLint** | **241KB** | **✅ KHÔNG (devDep)** | **Development + CI/CD** |
110
+ | TypeScript | ~60MB | ❌ Nếu để dependencies | Development only |
111
+
112
+ ### 6. Best Practices cho Teams
113
+
114
+ #### Developers:
115
+ ```bash
116
+ # Local development
117
+ npm install # Cài tất cả deps (bao gồm SunLint)
118
+ npx sunlint --quality --input=src
119
+
120
+ # Pre-commit hook
121
+ npx sunlint --changed-files
122
+ ```
123
+
124
+ #### CI/CD:
125
+ ```bash
126
+ # Build pipeline
127
+ npm ci # Cài tất cả deps
128
+ npx sunlint --all --input=src # Quality check
129
+ npm run build # Build production
130
+ npm prune --production # Xóa devDeps
131
+ ```
132
+
133
+ #### Production:
134
+ ```bash
135
+ # Server deployment
136
+ npm ci --only=production # Chỉ cài production deps
137
+ # → SunLint sẽ KHÔNG được cài
138
+ ```
139
+
140
+ ### 7. Monitoring & Verification
141
+
142
+ #### Verify production size:
143
+ ```bash
144
+ # Trước deploy
145
+ du -sh node_modules
146
+ du -sh dist/
147
+
148
+ # Kiểm tra không có SunLint
149
+ ls node_modules | grep sunlint # Không có kết quả = OK
150
+ ```
151
+
152
+ #### Bundle size monitoring:
153
+ ```bash
154
+ # Add to package.json
155
+ {
156
+ "scripts": {
157
+ "analyze-bundle": "du -sh dist/ && echo 'Production bundle size'",
158
+ "verify-prod": "npm ls --production --depth=0"
159
+ }
160
+ }
161
+ ```
162
+
163
+ ## Kết luận
164
+
165
+ ### ✅ AN TOÀN cho Production:
166
+ - SunLint được thiết kế như devDependency
167
+ - Không ảnh hưởng size production bundle khi sử dụng đúng
168
+ - Có thể tích hợp vào CI/CD mà không ảnh hưởng deployment
169
+
170
+ ### 📊 Số liệu cụ thể:
171
+ - **Development**: +88MB (chỉ khi dev)
172
+ - **Production**: +0KB (khi dùng đúng cách)
173
+ - **CI/CD**: Impact chỉ ở build time, không ở runtime
174
+
175
+ ### 🚀 Khuyến nghị:
176
+ 1. **Luôn cài như devDependency**
177
+ 2. **Sử dụng trong CI/CD pipeline**
178
+ 3. **npm prune --production trước deploy**
179
+ 4. **Monitor bundle size định kỳ**
180
+
181
+ ---
182
+
183
+ *Tài liệu này được cập nhật cho SunLint v1.1.4 - July 2025*
@@ -6,6 +6,7 @@
6
6
  */
7
7
 
8
8
  const AnalysisEngineInterface = require('../core/interfaces/analysis-engine.interface');
9
+ const dependencyChecker = require('../core/dependency-checker');
9
10
  const fs = require('fs');
10
11
  const path = require('path');
11
12
 
@@ -62,6 +63,9 @@ class ESLintEngine extends AnalysisEngineInterface {
62
63
  // Store verbosity setting for use in other methods
63
64
  this.verbose = config?.verbose || false;
64
65
 
66
+ // Check for ESLint dependencies first
67
+ dependencyChecker.checkAndNotify('eslint');
68
+
65
69
  // Dynamically import ESLint
66
70
  const { ESLint } = await this.loadESLint();
67
71
 
@@ -94,6 +98,11 @@ class ESLintEngine extends AnalysisEngineInterface {
94
98
  * @returns {Promise<Object>} ESLint module
95
99
  */
96
100
  async loadESLint() {
101
+ // Check if ESLint is available first
102
+ if (!dependencyChecker.isDependencyAvailable('eslint')) {
103
+ throw new Error('ESLint not available. Install with: npm install eslint');
104
+ }
105
+
97
106
  try {
98
107
  // Try to load ESLint from node_modules
99
108
  return await import('eslint');
@@ -7,6 +7,7 @@
7
7
 
8
8
  const AnalysisEngineInterface = require('../core/interfaces/analysis-engine.interface');
9
9
  const ASTModuleRegistry = require('../core/ast-modules/index');
10
+ const dependencyChecker = require('../core/dependency-checker');
10
11
  const fs = require('fs');
11
12
  const path = require('path');
12
13
 
@@ -30,6 +31,9 @@ class HeuristicEngine extends AnalysisEngineInterface {
30
31
  // Store verbosity setting
31
32
  this.verbose = config?.verbose || false;
32
33
 
34
+ // Check for optional AST dependencies
35
+ dependencyChecker.checkAndNotify('ast');
36
+
33
37
  // Load rules registry
34
38
  await this.loadRulesRegistry(config);
35
39
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@sun-asterisk/sunlint",
3
- "version": "1.1.3",
4
- "description": "☀️ Sun Lint - Universal Coding Standards | Multi-rule Quality & Security Analysis with ESLint Integration",
3
+ "version": "1.1.4",
4
+ "description": "☀️ SunLint - Multi-language static analysis tool for code quality and security | Sun* Engineering Standards",
5
5
  "main": "cli.js",
6
6
  "bin": {
7
7
  "sunlint": "./cli.js"
@@ -87,22 +87,49 @@
87
87
  },
88
88
  "dependencies": {
89
89
  "@babel/parser": "^7.23.0",
90
- "@typescript-eslint/parser": "^8.38.0",
90
+ "@typescript-eslint/eslint-plugin": "^7.18.0",
91
+ "@typescript-eslint/parser": "^7.18.0",
91
92
  "chalk": "^4.1.2",
92
93
  "commander": "^12.1.0",
94
+ "eslint": "^8.57.1",
95
+ "eslint-plugin-react": "^7.37.5",
96
+ "eslint-plugin-react-hooks": "^5.2.0",
93
97
  "espree": "^9.6.0",
94
- "glob": "^11.0.0",
95
98
  "minimatch": "^10.0.3",
96
99
  "node-fetch": "^3.3.2",
97
- "table": "^6.8.2",
98
- "typescript": "^5.7.2"
100
+ "table": "^6.8.2"
101
+ },
102
+ "peerDependencies": {
103
+ "typescript": ">=4.0.0"
104
+ },
105
+ "peerDependenciesMeta": {
106
+ "eslint": {
107
+ "optional": true
108
+ },
109
+ "@typescript-eslint/eslint-plugin": {
110
+ "optional": true
111
+ },
112
+ "@typescript-eslint/parser": {
113
+ "optional": true
114
+ },
115
+ "eslint-plugin-react": {
116
+ "optional": true
117
+ },
118
+ "eslint-plugin-react-hooks": {
119
+ "optional": true
120
+ },
121
+ "typescript": {
122
+ "optional": true
123
+ }
99
124
  },
100
125
  "devDependencies": {
101
126
  "@types/node": "^22.10.1",
102
127
  "@typescript-eslint/eslint-plugin": "^8.38.0",
103
128
  "@typescript-eslint/parser": "^8.38.0",
104
129
  "eslint": "^9.31.0",
105
- "jest": "^29.7.0"
130
+ "glob": "^11.0.3",
131
+ "jest": "^29.7.0",
132
+ "typescript": "^5.7.2"
106
133
  },
107
134
  "bugs": {
108
135
  "url": "https://github.com/sun-asterisk/engineer-excellence/issues"
@@ -1,87 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- const rule = require('./plugin/rules/common/c041-no-config-inline.js');
4
-
5
- // Simple test cases
6
- const testCases = [
7
- // Should NOT flag (false positives to avoid)
8
- { code: 'const inputType = "password";', shouldError: false, desc: 'InputType definition' },
9
- { code: 'const fieldType = "password";', shouldError: false, desc: 'Field type' },
10
- { code: 'const usePassword = "password_validation";', shouldError: false, desc: 'Hook usage' },
11
- { code: 'const testPassword = "test123";', shouldError: false, desc: 'Test data' },
12
- { code: 'const mockSecret = "mock_secret_key";', shouldError: false, desc: 'Mock data' },
13
- { code: 'const route = "/reset_password";', shouldError: false, desc: 'Route path' },
14
-
15
- // SHOULD flag (real sensitive data)
16
- { code: 'const dbPassword = "MySecretP@ssw0rd123";', shouldError: true, desc: 'Real hardcoded password' },
17
- { code: 'const apiKey = "sk-1234567890abcdef1234567890abcdef";', shouldError: true, desc: 'Real API key' },
18
- { code: 'const authToken = "bearer_token_12345678901234567";', shouldError: true, desc: 'Real auth token' }
19
- ];
20
-
21
- console.log('🧪 Testing ESLint C041 rule manually...\n');
22
-
23
- let passed = 0;
24
- let failed = 0;
25
-
26
- // Mock context for testing
27
- function createMockContext(code) {
28
- return {
29
- getSourceCode: () => ({
30
- lines: code.split('\n')
31
- }),
32
- report: ({ node, messageId }) => {
33
- return { reported: true, messageId };
34
- }
35
- };
36
- }
37
-
38
- testCases.forEach((testCase, index) => {
39
- try {
40
- let reported = false;
41
-
42
- // Parse the code to extract literal nodes (simplified)
43
- const literalMatch = testCase.code.match(/"([^"]+)"/);
44
- if (literalMatch) {
45
- const mockNode = {
46
- value: literalMatch[1],
47
- loc: { start: { line: 1 } }
48
- };
49
-
50
- const mockContext = {
51
- getSourceCode: () => ({
52
- lines: [testCase.code]
53
- }),
54
- report: ({ node, messageId }) => {
55
- reported = true;
56
- }
57
- };
58
-
59
- const ruleImplementation = rule.create(mockContext);
60
- ruleImplementation.Literal(mockNode);
61
- }
62
-
63
- const testPassed = reported === testCase.shouldError;
64
-
65
- if (testPassed) {
66
- console.log(`✅ Test ${index + 1}: ${testCase.desc}`);
67
- passed++;
68
- } else {
69
- console.log(`❌ Test ${index + 1}: ${testCase.desc}`);
70
- console.log(` Expected: ${testCase.shouldError ? 'Should flag' : 'Should NOT flag'}`);
71
- console.log(` Actual: ${reported ? 'Flagged' : 'Not flagged'}`);
72
- failed++;
73
- }
74
- } catch (error) {
75
- console.log(`💥 Test ${index + 1}: ${testCase.desc} - Error: ${error.message}`);
76
- failed++;
77
- }
78
- });
79
-
80
- console.log(`\n📊 Test Results: ${passed} passed, ${failed} failed`);
81
- console.log(`Success rate: ${Math.round((passed / (passed + failed)) * 100)}%`);
82
-
83
- if (failed === 0) {
84
- console.log('\n🎉 All ESLint rule tests passed!');
85
- } else {
86
- console.log('\n⚠️ Some tests failed. Review the rule logic.');
87
- }