@caspeco/eslint-config-react 5.0.0 → 5.0.1-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,106 +1,106 @@
1
- # @caspeco/eslint-config-react
2
-
3
- Caspeco ESLint configuration for React + TypeScript projects.
4
-
5
- ## Installation
6
-
7
- ```bash
8
- npm install --save-dev @caspeco/eslint-config-react
9
- ```
10
-
11
- ### Migrating from v4.x
12
-
13
- If you're upgrading from `@caspeco/eslint-config` v4.x, use the automated migration script:
14
-
15
- ```bash
16
- # Preview changes
17
- npx caspeco-react-migrate-v5 src/ --dry-run
18
-
19
- # Apply changes
20
- npx caspeco-react-migrate-v5 src/
21
- ```
22
-
23
- This updates the plugin namespace from `caspeco/` to `caspeco-react/`. See the [Migration Guide](../../MIGRATION.md) for details.
24
-
25
- ## Usage
26
-
27
- Create an `eslint.config.js` file in your project root:
28
-
29
- ```js
30
- import config from "@caspeco/eslint-config-react";
31
-
32
- export default [{ ignores: ["dist/**/*", "build/**/*"] }, ...config];
33
- ```
34
-
35
- ## What's Included
36
-
37
- This configuration includes everything from our TypeScript config plus React-specific rules:
38
-
39
- ### Base TypeScript Configuration
40
-
41
- - **TypeScript ESLint** - recommended-type-checked config
42
- - **No Barrel Files** - Prevents barrel file usage
43
- - **File Naming Conventions** - Enforces kebab-case for files and folders
44
- - **Prettier Integration** - Compatible with Prettier formatting
45
-
46
- ### React-Specific Configuration
47
-
48
- - **React Plugin** - Core React linting rules
49
- - **React Hooks** - Enforces rules of hooks
50
- - **React Refresh** - Fast Refresh support for Vite/development
51
- - **Caspeco Plugin** - Custom rules for Caspeco projects (Chakra UI import restrictions)
52
-
53
- ## Peer Dependencies
54
-
55
- This package requires the following peer dependencies (automatically installed by npm 7+):
56
-
57
- - `eslint`
58
- - `eslint-plugin-react`
59
- - `eslint-plugin-react-hooks`
60
- - `eslint-plugin-react-refresh`
61
- - `globals`
62
-
63
- See [package.json](./package.json) for specific version requirements.
64
-
65
- **Note:** Additional TypeScript-related peer dependencies are inherited from `@caspeco/eslint-config-ts` (installed automatically as a regular dependency).
66
-
67
- ## Plugins
68
-
69
- ### eslint-plugin-react
70
-
71
- [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react)
72
-
73
- Core React linting rules with the following customizations:
74
-
75
- - `react-in-jsx-scope`: off (not needed in modern React)
76
- - `prop-types`: off (using TypeScript instead)
77
- - `display-name`: off
78
-
79
- ### eslint-plugin-react-hooks
80
-
81
- [eslint-plugin-react-hooks](https://www.npmjs.com/package/eslint-plugin-react-hooks)
82
-
83
- Enforces:
84
-
85
- - Rules of Hooks (error)
86
- - Exhaustive dependencies (warning)
87
-
88
- ### eslint-plugin-react-refresh
89
-
90
- [eslint-plugin-react-refresh](https://github.com/ArnaudBarre/eslint-plugin-react-refresh)
91
-
92
- Ensures components are compatible with Fast Refresh in development.
93
-
94
- ### caspeco-react-plugin
95
-
96
- Custom React-specific plugin with Caspeco rules:
97
-
98
- - Discourages direct imports from `@chakra-ui/react` (use themed components instead)
99
-
100
- ## Relationship with @caspeco/eslint-config-ts
101
-
102
- This package depends on and extends `@caspeco/eslint-config-ts`, which is automatically installed as a dependency. This ensures React projects always use the same TypeScript rules without drift. If you're building a React project, use this package. For vanilla TypeScript projects, use `@caspeco/eslint-config-ts`.
103
-
104
- ## License
105
-
106
- MIT
1
+ # @caspeco/eslint-config-react
2
+
3
+ Caspeco ESLint configuration for React + TypeScript projects.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install --save-dev @caspeco/eslint-config-react
9
+ ```
10
+
11
+ ### Migrating from v4.x
12
+
13
+ If you're upgrading from `@caspeco/eslint-config` v4.x, use the automated migration script:
14
+
15
+ ```bash
16
+ # Preview changes
17
+ npx caspeco-react-migrate-v5 src/ --dry-run
18
+
19
+ # Apply changes
20
+ npx caspeco-react-migrate-v5 src/
21
+ ```
22
+
23
+ This updates the plugin namespace from `caspeco/` to `caspeco-react/`. See the [Migration Guide](../../MIGRATION.md) for details.
24
+
25
+ ## Usage
26
+
27
+ Create an `eslint.config.js` file in your project root:
28
+
29
+ ```js
30
+ import config from "@caspeco/eslint-config-react";
31
+
32
+ export default [{ ignores: ["dist/**/*", "build/**/*"] }, ...config];
33
+ ```
34
+
35
+ ## What's Included
36
+
37
+ This configuration includes everything from our TypeScript config plus React-specific rules:
38
+
39
+ ### Base TypeScript Configuration
40
+
41
+ - **TypeScript ESLint** - recommended-type-checked config
42
+ - **No Barrel Files** - Prevents barrel file usage
43
+ - **File Naming Conventions** - Enforces kebab-case for files and folders
44
+ - **Prettier Integration** - Compatible with Prettier formatting
45
+
46
+ ### React-Specific Configuration
47
+
48
+ - **React Plugin** - Core React linting rules
49
+ - **React Hooks** - Enforces rules of hooks
50
+ - **React Refresh** - Fast Refresh support for Vite/development
51
+ - **Caspeco Plugin** - Custom rules for Caspeco projects (Chakra UI import restrictions)
52
+
53
+ ## Peer Dependencies
54
+
55
+ This package requires the following peer dependencies (automatically installed by npm 7+):
56
+
57
+ - `eslint`
58
+ - `eslint-plugin-react`
59
+ - `eslint-plugin-react-hooks`
60
+ - `eslint-plugin-react-refresh`
61
+ - `globals`
62
+
63
+ See [package.json](./package.json) for specific version requirements.
64
+
65
+ **Note:** Additional TypeScript-related peer dependencies are inherited from `@caspeco/eslint-config-ts` (installed automatically as a regular dependency).
66
+
67
+ ## Plugins
68
+
69
+ ### eslint-plugin-react
70
+
71
+ [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react)
72
+
73
+ Core React linting rules with the following customizations:
74
+
75
+ - `react-in-jsx-scope`: off (not needed in modern React)
76
+ - `prop-types`: off (using TypeScript instead)
77
+ - `display-name`: off
78
+
79
+ ### eslint-plugin-react-hooks
80
+
81
+ [eslint-plugin-react-hooks](https://www.npmjs.com/package/eslint-plugin-react-hooks)
82
+
83
+ Enforces:
84
+
85
+ - Rules of Hooks (error)
86
+ - Exhaustive dependencies (warning)
87
+
88
+ ### eslint-plugin-react-refresh
89
+
90
+ [eslint-plugin-react-refresh](https://github.com/ArnaudBarre/eslint-plugin-react-refresh)
91
+
92
+ Ensures components are compatible with Fast Refresh in development.
93
+
94
+ ### caspeco-react-plugin
95
+
96
+ Custom React-specific plugin with Caspeco rules:
97
+
98
+ - Discourages direct imports from `@chakra-ui/react` (use themed components instead)
99
+
100
+ ## Relationship with @caspeco/eslint-config-ts
101
+
102
+ This package depends on and extends `@caspeco/eslint-config-ts`, which is automatically installed as a dependency. This ensures React projects always use the same TypeScript rules without drift. If you're building a React project, use this package. For vanilla TypeScript projects, use `@caspeco/eslint-config-ts`.
103
+
104
+ ## License
105
+
106
+ MIT
package/bin/README.md CHANGED
@@ -1,40 +1,40 @@
1
- # Migration Scripts
2
-
3
- ## caspeco-react-migrate-v5
4
-
5
- Automated migration script for updating from `@caspeco/eslint-config` v4.x to `@caspeco/eslint-config-react` v5.x.
6
-
7
- ### Usage
8
-
9
- ```bash
10
- # Preview changes (dry run)
11
- npx caspeco-react-migrate-v5 src/ --dry-run
12
-
13
- # Apply changes
14
- npx caspeco-react-migrate-v5 src/
15
-
16
- # Scan entire project
17
- npx caspeco-react-migrate-v5 .
18
- ```
19
-
20
- ### What it does
21
-
22
- - Updates rule names: `caspeco/discourage-chakra-import` → `caspeco-react/discourage-chakra-import`
23
- - Fixes ESLint disable comments
24
- - Updates config files
25
- - Processes `.js`, `.jsx`, `.ts`, `.tsx`, `.json`, and `.md` files
26
-
27
- ### Files processed
28
-
29
- The script automatically:
30
-
31
- - Skips `node_modules`, `.git`, `dist`, `build`, and `coverage` directories
32
- - Recursively processes all supported file types
33
- - Shows a summary of changes made
34
-
35
- ### Options
36
-
37
- - `--dry-run`: Preview changes without modifying files
38
- - First argument: Path to scan (defaults to current directory)
39
-
40
- See the [Migration Guide](../../../MIGRATION.md) for full migration instructions.
1
+ # Migration Scripts
2
+
3
+ ## caspeco-react-migrate-v5
4
+
5
+ Automated migration script for updating from `@caspeco/eslint-config` v4.x to `@caspeco/eslint-config-react` v5.x.
6
+
7
+ ### Usage
8
+
9
+ ```bash
10
+ # Preview changes (dry run)
11
+ npx caspeco-react-migrate-v5 src/ --dry-run
12
+
13
+ # Apply changes
14
+ npx caspeco-react-migrate-v5 src/
15
+
16
+ # Scan entire project
17
+ npx caspeco-react-migrate-v5 .
18
+ ```
19
+
20
+ ### What it does
21
+
22
+ - Updates rule names: `caspeco/discourage-chakra-import` → `caspeco-react/discourage-chakra-import`
23
+ - Fixes ESLint disable comments
24
+ - Updates config files
25
+ - Processes `.js`, `.jsx`, `.ts`, `.tsx`, `.json`, and `.md` files
26
+
27
+ ### Files processed
28
+
29
+ The script automatically:
30
+
31
+ - Skips `node_modules`, `.git`, `dist`, `build`, and `coverage` directories
32
+ - Recursively processes all supported file types
33
+ - Shows a summary of changes made
34
+
35
+ ### Options
36
+
37
+ - `--dry-run`: Preview changes without modifying files
38
+ - First argument: Path to scan (defaults to current directory)
39
+
40
+ See the [Migration Guide](../../../MIGRATION.md) for full migration instructions.
@@ -1,203 +1,203 @@
1
1
  #!/usr/bin/env node
2
-
3
- /**
4
- * Migration script for v4.x to v5.x
5
- *
6
- * This script updates:
7
- * - Package imports: @caspeco/eslint-config → @caspeco/eslint-config-react
8
- * - Named imports: { reactConfig } → default import reactConfig
9
- * - Rule names: caspeco/discourage-chakra-import → caspeco-react/discourage-chakra-import
10
- * - ESLint disable comments
11
- *
12
- * Handles both:
13
- * - Full migration: import { reactConfig } from "@caspeco/eslint-config"
14
- * - Partial migration: import { reactConfig } from "@caspeco/eslint-config-react"
15
- *
16
- * Usage:
17
- * npx caspeco-react-migrate-v5 [path] [--dry-run]
18
- *
19
- * Examples:
20
- * npx caspeco-react-migrate-v5 src/
21
- * npx caspeco-react-migrate-v5 . --dry-run
22
- */
23
-
24
- import fs from "fs";
25
- import path from "path";
26
- import { fileURLToPath } from "url";
27
-
28
- const __filename = fileURLToPath(import.meta.url);
29
- const __dirname = path.dirname(__filename);
30
-
31
- const args = process.argv.slice(2);
32
- const isDryRun = args.includes("--dry-run");
33
- const targetPath = args.find((arg) => !arg.startsWith("--")) || ".";
34
-
35
- // Patterns to search and replace
36
- const replacements = [
37
- {
38
- pattern: /caspeco\/discourage-chakra-import/g,
39
- replacement: "caspeco-react/discourage-chakra-import",
40
- description: "Rule name",
41
- },
42
- ];
43
-
44
- // Import transformation for eslint.config.js files
45
- function transformImports(content, filename) {
46
- if (!filename.includes("eslint.config.")) {
47
- return { content, hasChanges: false };
48
- }
49
-
50
- let transformed = content;
51
- let hasChanges = false;
52
-
53
- // Replace import { reactConfig } from "@caspeco/eslint-config" → import reactConfig from "@caspeco/eslint-config-react"
54
- // Also handle the case where package name is already updated but still using named import
55
- const oldPackagePattern = /import\s*\{\s*reactConfig\s*\}\s*from\s*["']@caspeco\/eslint-config["']/;
56
- const newPackagePattern = /import\s*\{\s*reactConfig\s*\}\s*from\s*["']@caspeco\/eslint-config-react["']/;
57
-
58
- if (oldPackagePattern.test(transformed)) {
59
- transformed = transformed.replace(
60
- oldPackagePattern,
61
- 'import reactConfig from "@caspeco/eslint-config-react"',
62
- );
63
- hasChanges = true;
64
- } else if (newPackagePattern.test(transformed)) {
65
- // Package name already updated, just change from named to default import
66
- transformed = transformed.replace(
67
- newPackagePattern,
68
- 'import reactConfig from "@caspeco/eslint-config-react"',
69
- );
70
- hasChanges = true;
71
- }
72
-
73
- return { content: transformed, hasChanges };
74
- }
75
-
76
- // File extensions to process
77
- const extensions = [".js", ".jsx", ".ts", ".tsx", ".json", ".md", ".mjs", ".cjs"];
78
-
79
- let filesProcessed = 0;
80
- let filesChanged = 0;
81
- let totalReplacements = 0;
82
-
83
- /**
84
- * Recursively process directory
85
- */
86
- function processDirectory(dir) {
87
- const entries = fs.readdirSync(dir, { withFileTypes: true });
88
-
89
- for (const entry of entries) {
90
- const fullPath = path.join(dir, entry.name);
91
-
92
- // Skip node_modules, .git, dist, build directories
93
- if (entry.isDirectory()) {
94
- if (["node_modules", ".git", "dist", "build", "coverage"].includes(entry.name)) {
95
- continue;
96
- }
97
- processDirectory(fullPath);
98
- } else {
99
- const ext = path.extname(entry.name);
100
- if (extensions.includes(ext)) {
101
- processFile(fullPath);
102
- }
103
- }
104
- }
105
- }
106
-
107
- /**
108
- * Process a single file
109
- */
110
- function processFile(filePath) {
111
- filesProcessed++;
112
-
113
- let content;
114
- try {
115
- content = fs.readFileSync(filePath, "utf8");
116
- } catch (err) {
117
- console.error(`Error reading ${filePath}:`, err.message);
118
- return;
119
- }
120
-
121
- let newContent = content;
122
- let fileReplacements = 0;
123
-
124
- // First, try import transformations for config files
125
- const filename = path.basename(filePath);
126
- const importResult = transformImports(newContent, filename);
127
- if (importResult.hasChanges) {
128
- newContent = importResult.content;
129
- fileReplacements++; // Count as one logical replacement (import + references)
130
- }
131
-
132
- // Then apply all other replacement patterns
133
- for (const { pattern, replacement } of replacements) {
134
- const matches = newContent.match(pattern);
135
- if (matches) {
136
- fileReplacements += matches.length;
137
- newContent = newContent.replace(pattern, replacement);
138
- }
139
- }
140
-
141
- // If changes were made
142
- if (fileReplacements > 0) {
143
- filesChanged++;
144
- totalReplacements += fileReplacements;
145
-
146
- const relativePath = path.relative(process.cwd(), filePath);
147
- console.log(
148
- `${isDryRun ? "[DRY RUN] " : ""}✓ ${relativePath} (${fileReplacements} replacement${fileReplacements > 1 ? "s" : ""})`,
149
- );
150
-
151
- if (!isDryRun) {
152
- try {
153
- fs.writeFileSync(filePath, newContent, "utf8");
154
- } catch (err) {
155
- console.error(`Error writing ${filePath}:`, err.message);
156
- }
157
- }
158
- }
159
- }
160
-
161
- /**
162
- * Main execution
163
- */
164
- function main() {
165
- console.log("Caspeco Plugin Migration Tool");
166
- console.log("==============================\n");
167
-
168
- if (isDryRun) {
169
- console.log("🔍 Running in DRY RUN mode - no files will be modified\n");
170
- }
171
-
172
- const resolvedPath = path.resolve(targetPath);
173
-
174
- if (!fs.existsSync(resolvedPath)) {
175
- console.error(`Error: Path "${targetPath}" does not exist`);
176
- process.exit(1);
177
- }
178
-
179
- console.log(`Scanning: ${resolvedPath}\n`);
180
-
181
- const stat = fs.statSync(resolvedPath);
182
- if (stat.isDirectory()) {
183
- processDirectory(resolvedPath);
184
- } else {
185
- processFile(resolvedPath);
186
- }
187
-
188
- console.log("\nSummary:");
189
- console.log("========");
190
- console.log(`Files scanned: ${filesProcessed}`);
191
- console.log(`Files with changes: ${filesChanged}`);
192
- console.log(`Total replacements: ${totalReplacements}`);
193
-
194
- if (isDryRun && filesChanged > 0) {
195
- console.log("\n💡 Run without --dry-run to apply changes");
196
- } else if (filesChanged > 0) {
197
- console.log("\n✅ Migration complete!");
198
- } else {
199
- console.log("\n✨ No files needed migration");
200
- }
201
- }
202
-
203
- main();
2
+
3
+ /**
4
+ * Migration script for v4.x to v5.x
5
+ *
6
+ * This script updates:
7
+ * - Package imports: @caspeco/eslint-config → @caspeco/eslint-config-react
8
+ * - Named imports: { reactConfig } → default import reactConfig
9
+ * - Rule names: caspeco/discourage-chakra-import → caspeco-react/discourage-chakra-import
10
+ * - ESLint disable comments
11
+ *
12
+ * Handles both:
13
+ * - Full migration: import { reactConfig } from "@caspeco/eslint-config"
14
+ * - Partial migration: import { reactConfig } from "@caspeco/eslint-config-react"
15
+ *
16
+ * Usage:
17
+ * npx caspeco-react-migrate-v5 [path] [--dry-run]
18
+ *
19
+ * Examples:
20
+ * npx caspeco-react-migrate-v5 src/
21
+ * npx caspeco-react-migrate-v5 . --dry-run
22
+ */
23
+
24
+ import fs from "fs";
25
+ import path from "path";
26
+ import { fileURLToPath } from "url";
27
+
28
+ const __filename = fileURLToPath(import.meta.url);
29
+ const __dirname = path.dirname(__filename);
30
+
31
+ const args = process.argv.slice(2);
32
+ const isDryRun = args.includes("--dry-run");
33
+ const targetPath = args.find((arg) => !arg.startsWith("--")) || ".";
34
+
35
+ // Patterns to search and replace
36
+ const replacements = [
37
+ {
38
+ pattern: /caspeco\/discourage-chakra-import/g,
39
+ replacement: "caspeco-react/discourage-chakra-import",
40
+ description: "Rule name",
41
+ },
42
+ ];
43
+
44
+ // Import transformation for eslint.config.js files
45
+ function transformImports(content, filename) {
46
+ if (!filename.includes("eslint.config.")) {
47
+ return { content, hasChanges: false };
48
+ }
49
+
50
+ let transformed = content;
51
+ let hasChanges = false;
52
+
53
+ // Replace import { reactConfig } from "@caspeco/eslint-config" → import reactConfig from "@caspeco/eslint-config-react"
54
+ // Also handle the case where package name is already updated but still using named import
55
+ const oldPackagePattern = /import\s*\{\s*reactConfig\s*\}\s*from\s*["']@caspeco\/eslint-config["']/;
56
+ const newPackagePattern = /import\s*\{\s*reactConfig\s*\}\s*from\s*["']@caspeco\/eslint-config-react["']/;
57
+
58
+ if (oldPackagePattern.test(transformed)) {
59
+ transformed = transformed.replace(
60
+ oldPackagePattern,
61
+ 'import reactConfig from "@caspeco/eslint-config-react"',
62
+ );
63
+ hasChanges = true;
64
+ } else if (newPackagePattern.test(transformed)) {
65
+ // Package name already updated, just change from named to default import
66
+ transformed = transformed.replace(
67
+ newPackagePattern,
68
+ 'import reactConfig from "@caspeco/eslint-config-react"',
69
+ );
70
+ hasChanges = true;
71
+ }
72
+
73
+ return { content: transformed, hasChanges };
74
+ }
75
+
76
+ // File extensions to process
77
+ const extensions = [".js", ".jsx", ".ts", ".tsx", ".json", ".md", ".mjs", ".cjs"];
78
+
79
+ let filesProcessed = 0;
80
+ let filesChanged = 0;
81
+ let totalReplacements = 0;
82
+
83
+ /**
84
+ * Recursively process directory
85
+ */
86
+ function processDirectory(dir) {
87
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
88
+
89
+ for (const entry of entries) {
90
+ const fullPath = path.join(dir, entry.name);
91
+
92
+ // Skip node_modules, .git, dist, build directories
93
+ if (entry.isDirectory()) {
94
+ if (["node_modules", ".git", "dist", "build", "coverage"].includes(entry.name)) {
95
+ continue;
96
+ }
97
+ processDirectory(fullPath);
98
+ } else {
99
+ const ext = path.extname(entry.name);
100
+ if (extensions.includes(ext)) {
101
+ processFile(fullPath);
102
+ }
103
+ }
104
+ }
105
+ }
106
+
107
+ /**
108
+ * Process a single file
109
+ */
110
+ function processFile(filePath) {
111
+ filesProcessed++;
112
+
113
+ let content;
114
+ try {
115
+ content = fs.readFileSync(filePath, "utf8");
116
+ } catch (err) {
117
+ console.error(`Error reading ${filePath}:`, err.message);
118
+ return;
119
+ }
120
+
121
+ let newContent = content;
122
+ let fileReplacements = 0;
123
+
124
+ // First, try import transformations for config files
125
+ const filename = path.basename(filePath);
126
+ const importResult = transformImports(newContent, filename);
127
+ if (importResult.hasChanges) {
128
+ newContent = importResult.content;
129
+ fileReplacements++; // Count as one logical replacement (import + references)
130
+ }
131
+
132
+ // Then apply all other replacement patterns
133
+ for (const { pattern, replacement } of replacements) {
134
+ const matches = newContent.match(pattern);
135
+ if (matches) {
136
+ fileReplacements += matches.length;
137
+ newContent = newContent.replace(pattern, replacement);
138
+ }
139
+ }
140
+
141
+ // If changes were made
142
+ if (fileReplacements > 0) {
143
+ filesChanged++;
144
+ totalReplacements += fileReplacements;
145
+
146
+ const relativePath = path.relative(process.cwd(), filePath);
147
+ console.log(
148
+ `${isDryRun ? "[DRY RUN] " : ""}✓ ${relativePath} (${fileReplacements} replacement${fileReplacements > 1 ? "s" : ""})`,
149
+ );
150
+
151
+ if (!isDryRun) {
152
+ try {
153
+ fs.writeFileSync(filePath, newContent, "utf8");
154
+ } catch (err) {
155
+ console.error(`Error writing ${filePath}:`, err.message);
156
+ }
157
+ }
158
+ }
159
+ }
160
+
161
+ /**
162
+ * Main execution
163
+ */
164
+ function main() {
165
+ console.log("Caspeco Plugin Migration Tool");
166
+ console.log("==============================\n");
167
+
168
+ if (isDryRun) {
169
+ console.log("🔍 Running in DRY RUN mode - no files will be modified\n");
170
+ }
171
+
172
+ const resolvedPath = path.resolve(targetPath);
173
+
174
+ if (!fs.existsSync(resolvedPath)) {
175
+ console.error(`Error: Path "${targetPath}" does not exist`);
176
+ process.exit(1);
177
+ }
178
+
179
+ console.log(`Scanning: ${resolvedPath}\n`);
180
+
181
+ const stat = fs.statSync(resolvedPath);
182
+ if (stat.isDirectory()) {
183
+ processDirectory(resolvedPath);
184
+ } else {
185
+ processFile(resolvedPath);
186
+ }
187
+
188
+ console.log("\nSummary:");
189
+ console.log("========");
190
+ console.log(`Files scanned: ${filesProcessed}`);
191
+ console.log(`Files with changes: ${filesChanged}`);
192
+ console.log(`Total replacements: ${totalReplacements}`);
193
+
194
+ if (isDryRun && filesChanged > 0) {
195
+ console.log("\n💡 Run without --dry-run to apply changes");
196
+ } else if (filesChanged > 0) {
197
+ console.log("\n✅ Migration complete!");
198
+ } else {
199
+ console.log("\n✨ No files needed migration");
200
+ }
201
+ }
202
+
203
+ main();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@caspeco/eslint-config-react",
3
- "version": "5.0.0",
3
+ "version": "5.0.1-beta.1",
4
4
  "description": "Caspeco ESLint configuration for React projects",
5
5
  "keywords": [
6
6
  "eslint",
@@ -32,7 +32,7 @@
32
32
  "test": "vitest"
33
33
  },
34
34
  "dependencies": {
35
- "@caspeco/eslint-config-ts": "5.0.0"
35
+ "@caspeco/eslint-config-ts": "5.0.1-beta.1"
36
36
  },
37
37
  "devDependencies": {
38
38
  "@caspeco/test-utils": "*"
@@ -44,6 +44,10 @@
44
44
  "eslint-plugin-react-refresh": ">=0.4.0",
45
45
  "globals": ">=15"
46
46
  },
47
+ "engines": {
48
+ "node": ">=24",
49
+ "npm": ">=11.5.1"
50
+ },
47
51
  "publishConfig": {
48
52
  "access": "public"
49
53
  }
package/src/index.js CHANGED
@@ -1,74 +1,74 @@
1
- import tsConfig from "@caspeco/eslint-config-ts";
2
- import reactRefresh from "eslint-plugin-react-refresh";
3
- import reactPlugin from "eslint-plugin-react";
4
- import reactHooksPlugin from "eslint-plugin-react-hooks";
5
- import caspecoReactPlugin from "./plugins/caspeco-react.js";
6
- import globals from "globals";
7
-
8
- /** @type {import('@typescript-eslint/utils').TSESLint.FlatConfig.ConfigArray} */
9
- const flatConfig = [
10
- // Extend the vanilla TypeScript config
11
- ...tsConfig,
12
- // React plugin recommended config
13
- {
14
- ...reactPlugin.configs.flat?.recommended,
15
- files: ["**/*.ts", "**/*.tsx", "**/*.jsx"],
16
- settings: {
17
- react: {
18
- version: "detect",
19
- },
20
- },
21
- languageOptions: {
22
- ...reactPlugin.configs.flat?.recommended.languageOptions,
23
- globals: {
24
- ...globals.serviceworker,
25
- ...globals.browser,
26
- },
27
- parserOptions: {
28
- ...reactPlugin.configs.flat?.recommended.languageOptions?.parserOptions,
29
- ecmaVersion: "latest",
30
- },
31
- },
32
- rules: {
33
- ...reactPlugin.configs.flat?.recommended.rules,
34
- "react/react-in-jsx-scope": "off",
35
- "react/prop-types": "off",
36
- "react/display-name": "off",
37
- },
38
- },
39
- // React hooks plugin recommended config
40
- {
41
- ...reactHooksPlugin.configs.recommended,
42
- plugins: { "react-hooks": reactHooksPlugin },
43
- files: ["**/*.ts", "**/*.tsx", "**/*.jsx"],
44
- rules: {
45
- "react-hooks/rules-of-hooks": "error",
46
- "react-hooks/exhaustive-deps": "warn",
47
- // We ignore the compiler specific rules as we need React 19 for this.
48
- // https://github.com/facebook/react/tree/main/packages/eslint-plugin-react-hooks#flat-config-eslintconfigjsts-1
49
- // When we support this, we can add:
50
- // ...reactHooksPlugin.configs.recommended.rules,
51
- },
52
- },
53
- // React refresh plugin config
54
- {
55
- ...reactRefresh.configs.recommended,
56
- files: ["**/*.ts", "**/*.tsx", "**/*.jsx"],
57
- rules: {
58
- ...reactRefresh.configs.recommended.rules,
59
- "react-refresh/only-export-components": ["warn", { allowConstantExport: true }],
60
- },
61
- },
62
- // Caspeco React custom rules
63
- {
64
- files: ["**/*.ts", "**/*.tsx", "**/*.jsx"],
65
- plugins: {
66
- "caspeco-react": caspecoReactPlugin,
67
- },
68
- rules: {
69
- "caspeco-react/discourage-chakra-import": "error",
70
- },
71
- },
72
- ];
73
-
74
- export default flatConfig;
1
+ import tsConfig from "@caspeco/eslint-config-ts";
2
+ import reactRefresh from "eslint-plugin-react-refresh";
3
+ import reactPlugin from "eslint-plugin-react";
4
+ import reactHooksPlugin from "eslint-plugin-react-hooks";
5
+ import caspecoReactPlugin from "./plugins/caspeco-react.js";
6
+ import globals from "globals";
7
+
8
+ /** @type {import('@typescript-eslint/utils').TSESLint.FlatConfig.ConfigArray} */
9
+ const flatConfig = [
10
+ // Extend the vanilla TypeScript config
11
+ ...tsConfig,
12
+ // React plugin recommended config
13
+ {
14
+ ...reactPlugin.configs.flat?.recommended,
15
+ files: ["**/*.ts", "**/*.tsx", "**/*.jsx"],
16
+ settings: {
17
+ react: {
18
+ version: "detect",
19
+ },
20
+ },
21
+ languageOptions: {
22
+ ...reactPlugin.configs.flat?.recommended.languageOptions,
23
+ globals: {
24
+ ...globals.serviceworker,
25
+ ...globals.browser,
26
+ },
27
+ parserOptions: {
28
+ ...reactPlugin.configs.flat?.recommended.languageOptions?.parserOptions,
29
+ ecmaVersion: "latest",
30
+ },
31
+ },
32
+ rules: {
33
+ ...reactPlugin.configs.flat?.recommended.rules,
34
+ "react/react-in-jsx-scope": "off",
35
+ "react/prop-types": "off",
36
+ "react/display-name": "off",
37
+ },
38
+ },
39
+ // React hooks plugin recommended config
40
+ {
41
+ ...reactHooksPlugin.configs.recommended,
42
+ plugins: { "react-hooks": reactHooksPlugin },
43
+ files: ["**/*.ts", "**/*.tsx", "**/*.jsx"],
44
+ rules: {
45
+ "react-hooks/rules-of-hooks": "error",
46
+ "react-hooks/exhaustive-deps": "warn",
47
+ // We ignore the compiler specific rules as we need React 19 for this.
48
+ // https://github.com/facebook/react/tree/main/packages/eslint-plugin-react-hooks#flat-config-eslintconfigjsts-1
49
+ // When we support this, we can add:
50
+ // ...reactHooksPlugin.configs.recommended.rules,
51
+ },
52
+ },
53
+ // React refresh plugin config
54
+ {
55
+ ...reactRefresh.configs.recommended,
56
+ files: ["**/*.ts", "**/*.tsx", "**/*.jsx"],
57
+ rules: {
58
+ ...reactRefresh.configs.recommended.rules,
59
+ "react-refresh/only-export-components": ["warn", { allowConstantExport: true }],
60
+ },
61
+ },
62
+ // Caspeco React custom rules
63
+ {
64
+ files: ["**/*.ts", "**/*.tsx", "**/*.jsx"],
65
+ plugins: {
66
+ "caspeco-react": caspecoReactPlugin,
67
+ },
68
+ rules: {
69
+ "caspeco-react/discourage-chakra-import": "error",
70
+ },
71
+ },
72
+ ];
73
+
74
+ export default flatConfig;
@@ -1,45 +1,45 @@
1
- /**
2
- * @typedef {import("eslint").Rule.RuleModule} Rule
3
- */
4
-
5
- /**
6
- * @type {{ rules: { [key: string]: Rule } }}
7
- */
8
- const caspeco = {
9
- rules: {
10
- "discourage-chakra-import": {
11
- meta: {
12
- type: "suggestion",
13
- docs: {
14
- description:
15
- 'Discourage importing anything from "@chakra-ui/*". Use imports from "@caspeco/casper-ui-library" instead.',
16
- category: "Best Practices",
17
- url: "https://caspeco.github.io/eslint-config/#/plugins/caspeco?id=caspecodiscourage-chakra-import",
18
- recommended: false,
19
- },
20
- messages: {
21
- restrictedImport: "Importing from {{importPath}} is discouraged.",
22
- },
23
- schema: [],
24
- },
25
- create(context) {
26
- return {
27
- ImportDeclaration(node) {
28
- const importPath = node.source.value;
29
- if (typeof importPath === "string" && importPath.startsWith("@chakra-ui/")) {
30
- context.report({
31
- node,
32
- messageId: "restrictedImport",
33
- data: {
34
- importPath,
35
- },
36
- });
37
- }
38
- },
39
- };
40
- },
41
- },
42
- },
43
- };
44
-
45
- export default caspeco;
1
+ /**
2
+ * @typedef {import("eslint").Rule.RuleModule} Rule
3
+ */
4
+
5
+ /**
6
+ * @type {{ rules: { [key: string]: Rule } }}
7
+ */
8
+ const caspeco = {
9
+ rules: {
10
+ "discourage-chakra-import": {
11
+ meta: {
12
+ type: "suggestion",
13
+ docs: {
14
+ description:
15
+ 'Discourage importing anything from "@chakra-ui/*". Use imports from "@caspeco/casper-ui-library" instead.',
16
+ category: "Best Practices",
17
+ url: "https://caspeco.github.io/eslint-config/#/plugins/caspeco?id=caspecodiscourage-chakra-import",
18
+ recommended: false,
19
+ },
20
+ messages: {
21
+ restrictedImport: "Importing from {{importPath}} is discouraged.",
22
+ },
23
+ schema: [],
24
+ },
25
+ create(context) {
26
+ return {
27
+ ImportDeclaration(node) {
28
+ const importPath = node.source.value;
29
+ if (typeof importPath === "string" && importPath.startsWith("@chakra-ui/")) {
30
+ context.report({
31
+ node,
32
+ messageId: "restrictedImport",
33
+ data: {
34
+ importPath,
35
+ },
36
+ });
37
+ }
38
+ },
39
+ };
40
+ },
41
+ },
42
+ },
43
+ };
44
+
45
+ export default caspeco;