@dimensional-innovations/tool-config 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +646 -0
  3. package/bin/setup-tool-config.js +675 -0
  4. package/package.json +168 -0
  5. package/src/detectors.js +261 -0
  6. package/src/index.js +64 -0
  7. package/src/tools/eslint/index.js +287 -0
  8. package/src/tools/eslint/presets/base.js +82 -0
  9. package/src/tools/eslint/presets/environments/browser.js +16 -0
  10. package/src/tools/eslint/presets/environments/node.js +21 -0
  11. package/src/tools/eslint/presets/environments/universal.js +18 -0
  12. package/src/tools/eslint/presets/frameworks/angular.js +74 -0
  13. package/src/tools/eslint/presets/frameworks/astro.js +38 -0
  14. package/src/tools/eslint/presets/frameworks/node.js +57 -0
  15. package/src/tools/eslint/presets/frameworks/react.js +76 -0
  16. package/src/tools/eslint/presets/frameworks/solid.js +45 -0
  17. package/src/tools/eslint/presets/frameworks/svelte.js +78 -0
  18. package/src/tools/eslint/presets/frameworks/vanilla.js +16 -0
  19. package/src/tools/eslint/presets/frameworks/vue.js +125 -0
  20. package/src/tools/eslint/presets/imports.js +41 -0
  21. package/src/tools/eslint/presets/typescript.js +131 -0
  22. package/src/tools/prettier/README.md +398 -0
  23. package/src/tools/prettier/index.js +114 -0
  24. package/src/tools/prettier/presets/base.js +36 -0
  25. package/src/tools/prettier/presets/frameworks/astro.js +15 -0
  26. package/src/tools/prettier/presets/frameworks/react.js +15 -0
  27. package/src/tools/prettier/presets/frameworks/svelte.js +22 -0
  28. package/src/tools/prettier/presets/frameworks/vanilla.js +13 -0
  29. package/src/tools/prettier/presets/frameworks/vue.js +20 -0
  30. package/src/tools/prettier/presets/prettierignore.js +56 -0
  31. package/src/tools/semantic-release/CI_SETUP.md +66 -0
  32. package/src/tools/semantic-release/README.md +533 -0
  33. package/src/tools/semantic-release/index.js +130 -0
  34. package/src/tools/semantic-release/presets/default.js +37 -0
  35. package/src/tools/semantic-release/presets/library.js +58 -0
  36. package/src/tools/semantic-release/presets/monorepo.js +48 -0
  37. package/src/tools/semantic-release/templates/.gitlab-ci.yml +85 -0
  38. package/src/tools/semantic-release/templates/bitbucket-pipelines.yml +100 -0
  39. package/src/tools/semantic-release/templates/github-workflow.yml +107 -0
  40. package/src/tools/stylelint/README.md +425 -0
  41. package/src/tools/stylelint/index.js +191 -0
  42. package/src/tools/stylelint/presets/base.js +50 -0
  43. package/src/tools/stylelint/presets/css-modules.js +43 -0
  44. package/src/tools/stylelint/presets/frameworks/react.js +18 -0
  45. package/src/tools/stylelint/presets/frameworks/svelte.js +28 -0
  46. package/src/tools/stylelint/presets/frameworks/vanilla.js +14 -0
  47. package/src/tools/stylelint/presets/frameworks/vue.js +38 -0
  48. package/src/tools/stylelint/presets/scss.js +83 -0
  49. package/src/tools/stylelint/presets/tailwind.js +49 -0
  50. package/src/utils/package-reader.js +42 -0
@@ -0,0 +1,287 @@
1
+ import js from '@eslint/js'
2
+ import tseslint from 'typescript-eslint'
3
+
4
+ import { autoDetect } from '../../detectors.js'
5
+
6
+ import basePreset from './presets/base.js'
7
+ import browserEnv from './presets/environments/browser.js'
8
+ import nodeEnv from './presets/environments/node.js'
9
+ import universalEnv from './presets/environments/universal.js'
10
+ import createAngularPreset from './presets/frameworks/angular.js'
11
+ import createNodePreset from './presets/frameworks/node.js'
12
+ import createReactPreset from './presets/frameworks/react.js'
13
+ import createVanillaPreset from './presets/frameworks/vanilla.js'
14
+ import createVuePreset from './presets/frameworks/vue.js'
15
+ import importsPreset from './presets/imports.js'
16
+ import typescriptPreset from './presets/typescript.js'
17
+
18
+ /**
19
+ * File patterns for all supported source file types
20
+ */
21
+ const SOURCE_FILES = [
22
+ '**/*.js',
23
+ '**/*.ts',
24
+ '**/*.tsx',
25
+ '**/*.vue',
26
+ '**/*.jsx',
27
+ '**/*.svelte',
28
+ '**/*.astro'
29
+ ]
30
+
31
+ /**
32
+ * Add framework-specific configuration to config array
33
+ * Supports lazy loading for Svelte, Solid, and Astro to avoid requiring optional peer dependencies
34
+ *
35
+ * @param {Array} config - ESLint flat config array to append framework presets to
36
+ * @param {string} framework - Framework name ('react' | 'vue' | 'svelte' | 'solid' | 'astro' | 'angular' | 'vanilla' | 'node')
37
+ * @returns {Promise<void>}
38
+ */
39
+ async function addFrameworkConfig(config, framework) {
40
+ switch (framework) {
41
+ case 'react':
42
+ config.push(...createReactPreset())
43
+ break
44
+ case 'vue':
45
+ config.push(...createVuePreset())
46
+ break
47
+ case 'svelte': {
48
+ const { default: createSveltePreset } = await import('./presets/frameworks/svelte.js')
49
+ config.push(...createSveltePreset())
50
+ break
51
+ }
52
+ case 'solid': {
53
+ const { default: createSolidPreset } = await import('./presets/frameworks/solid.js')
54
+ config.push(...createSolidPreset())
55
+ break
56
+ }
57
+ case 'astro': {
58
+ const { default: createAstroPreset } = await import('./presets/frameworks/astro.js')
59
+ config.push(...createAstroPreset())
60
+ break
61
+ }
62
+ case 'vanilla':
63
+ config.push(...createVanillaPreset())
64
+ break
65
+ case 'node':
66
+ config.push(...createNodePreset())
67
+ break
68
+ case 'angular':
69
+ config.push(...createAngularPreset())
70
+ break
71
+ default:
72
+ console.warn(`⚠️ Unknown framework "${framework}", defaulting to vanilla JavaScript`)
73
+ config.push(...createVanillaPreset())
74
+ break
75
+ }
76
+ }
77
+
78
+ /**
79
+ * Get environment configuration based on detected or specified environment
80
+ * Returns globals and languageOptions for browser, node, or universal environments
81
+ *
82
+ * @param {string} environment - Environment type ('browser' | 'node' | 'universal')
83
+ * @returns {Object} Environment configuration object with languageOptions
84
+ */
85
+ function getEnvironmentConfig(environment) {
86
+ switch (environment) {
87
+ case 'node':
88
+ return nodeEnv
89
+ case 'universal':
90
+ return universalEnv
91
+ case 'browser':
92
+ default:
93
+ return browserEnv
94
+ }
95
+ }
96
+
97
+ /**
98
+ * Add TypeScript configuration to config array
99
+ * Includes recommended TypeScript rules with relaxed settings for .d.ts and .js files
100
+ *
101
+ * @param {Array} config - ESLint flat config array to append TypeScript presets to
102
+ * @returns {void}
103
+ */
104
+ function addTypeScriptConfig(config) {
105
+ config.push(...tseslint.configs.recommended)
106
+ config.push({
107
+ files: SOURCE_FILES,
108
+ ...typescriptPreset
109
+ })
110
+
111
+ config.push({
112
+ files: ['**/*.d.ts'],
113
+ rules: {
114
+ '@typescript-eslint/no-explicit-any': 'off'
115
+ }
116
+ })
117
+
118
+ config.push({
119
+ files: ['**/*.js'],
120
+ rules: {
121
+ '@typescript-eslint/no-var-requires': 'off'
122
+ }
123
+ })
124
+ }
125
+
126
+ /**
127
+ * Add test and script overrides to config array
128
+ * Relaxes rules for test files and CLI scripts, and applies user-provided rule overrides
129
+ *
130
+ * @param {Array} config - ESLint flat config array to append overrides to
131
+ * @param {Object} options - Configuration options containing user rule overrides
132
+ * @param {Object} [options.rules] - User-provided rule overrides
133
+ * @returns {void}
134
+ */
135
+ function addOverrides(config, options) {
136
+ // Test files override
137
+ config.push({
138
+ files: ['tests/**/*.{js,ts,jsx,tsx,vue,svelte,astro}'],
139
+ rules: {
140
+ 'no-console': 'off',
141
+ 'max-lines-per-function': 'off',
142
+ complexity: 'off',
143
+ 'max-statements': 'off',
144
+ 'max-nested-callbacks': 'off',
145
+ 'no-magic-numbers': 'off',
146
+ '@typescript-eslint/no-explicit-any': 'off'
147
+ }
148
+ })
149
+
150
+ // Node.js scripts override
151
+ config.push({
152
+ files: ['**/bin/**/*.js', '**/scripts/**/*.js'],
153
+ languageOptions: {
154
+ globals: {
155
+ ...nodeEnv.languageOptions.globals
156
+ }
157
+ },
158
+ rules: {
159
+ 'no-console': 'off',
160
+ 'max-lines-per-function': 'off'
161
+ }
162
+ })
163
+
164
+ // User-provided rule overrides
165
+ if (options.rules && Object.keys(options.rules).length > 0) {
166
+ config.push({
167
+ files: SOURCE_FILES,
168
+ rules: options.rules
169
+ })
170
+ }
171
+ }
172
+
173
+ /**
174
+ * Create an ESLint flat config
175
+ *
176
+ * Supports: React, Vue.js, Svelte, Solid, Astro, Angular, Vanilla JS/TS, and auto-detection
177
+ *
178
+ * @param {Object} options - Configuration options
179
+ * @param {string} [options.framework='auto'] - Framework: 'auto' | 'react' | 'vue' | 'svelte' | 'solid' | 'astro' | 'angular' | 'vanilla' | 'node'
180
+ * @param {string} [options.environment='auto'] - Environment: 'auto' | 'browser' | 'node' | 'universal'
181
+ * @param {boolean|string} [options.typescript='auto'] - TypeScript: 'auto' | true | false
182
+ * @param {string[]} [options.ignorePaths=[]] - Additional paths to ignore during linting
183
+ * @param {Object} [options.rules={}] - Additional rule overrides
184
+ * @param {string} [options.cwd] - Current working directory for detection
185
+ * @returns {Promise<Array>} ESLint flat config array
186
+ *
187
+ * @example
188
+ * // Zero config - auto-detects everything
189
+ * import { createEslintConfig } from '@dimensional-innovations/tool-config';
190
+ * export default await createEslintConfig();
191
+ *
192
+ * @example
193
+ * // Explicit configuration
194
+ * import { createEslintConfig } from '@dimensional-innovations/tool-config';
195
+ * export default await createEslintConfig({
196
+ * framework: 'react',
197
+ * environment: 'browser',
198
+ * typescript: true
199
+ * });
200
+ *
201
+ * @example
202
+ * // With custom rules
203
+ * import { createEslintConfig } from '@dimensional-innovations/tool-config';
204
+ * export default await createEslintConfig({
205
+ * rules: {
206
+ * 'no-console': 'off'
207
+ * }
208
+ * });
209
+ */
210
+ export async function createEslintConfig(options = {}) {
211
+ const cwd = options.cwd || process.cwd()
212
+ const detected = autoDetect(cwd)
213
+
214
+ const framework =
215
+ options.framework === 'auto' || !options.framework ? detected.framework : options.framework
216
+ const environment =
217
+ options.environment === 'auto' || !options.environment
218
+ ? detected.environment
219
+ : options.environment
220
+ const typescript =
221
+ options.typescript === 'auto' || options.typescript === undefined
222
+ ? detected.typescript
223
+ : options.typescript
224
+
225
+ console.log(
226
+ `📦 ESLint Config: ${framework} | ${environment} | TypeScript: ${typescript ? 'Yes' : 'No'}`
227
+ )
228
+
229
+ if (framework === 'angular') {
230
+ console.warn(
231
+ '\n⚠️ Angular detected. This package provides basic TypeScript linting.\n' +
232
+ ' For Angular-specific rules, install: @angular-eslint/eslint-plugin\n' +
233
+ ' See: https://github.com/angular-eslint/angular-eslint\n'
234
+ )
235
+ }
236
+
237
+ const defaultIgnorePaths = [
238
+ '**/node_modules/**',
239
+ '**/dist/**',
240
+ '**/build/**',
241
+ '**/.next/**',
242
+ '**/.nuxt/**'
243
+ ]
244
+ const allIgnorePaths = [...defaultIgnorePaths, ...(options.ignorePaths || [])]
245
+
246
+ const config = []
247
+
248
+ // 1. Ignore paths
249
+ config.push({ ignores: allIgnorePaths })
250
+
251
+ // 2. ESLint recommended rules
252
+ config.push(js.configs.recommended)
253
+
254
+ // 3. TypeScript configuration
255
+ if (typescript) {
256
+ addTypeScriptConfig(config)
257
+ }
258
+
259
+ // 4. Environment configuration
260
+ const envConfig = getEnvironmentConfig(environment)
261
+ config.push({
262
+ files: SOURCE_FILES,
263
+ ...envConfig
264
+ })
265
+
266
+ // 5. Base JavaScript rules
267
+ config.push({
268
+ files: SOURCE_FILES,
269
+ ...basePreset
270
+ })
271
+
272
+ // 6. Import/export rules
273
+ config.push({
274
+ files: SOURCE_FILES,
275
+ ...importsPreset
276
+ })
277
+
278
+ // 7. Framework-specific configuration
279
+ await addFrameworkConfig(config, framework)
280
+
281
+ // 8. Test files and script overrides
282
+ addOverrides(config, options)
283
+
284
+ return config
285
+ }
286
+
287
+ export default createEslintConfig
@@ -0,0 +1,82 @@
1
+ /**
2
+ * Base JavaScript rules that apply to all projects
3
+ * These are framework-agnostic and environment-agnostic
4
+ */
5
+ export default {
6
+ rules: {
7
+ // ============================================================
8
+ // MODERN JAVASCRIPT RULES
9
+ // Best practices for ES2015+ code
10
+ // Documentation: https://eslint.org/docs/rules/
11
+ // ============================================================
12
+
13
+ // Console and debugging
14
+ 'no-console': ['warn', { allow: ['warn', 'error'] }], // Warn on console.log but allow console.warn/error for logging
15
+ 'no-debugger': 'warn', // Warn on debugger statements (should be removed before commit)
16
+ 'no-alert': 'error', // Disallow alert/confirm/prompt (use proper UI)
17
+
18
+ // Modern syntax preferences
19
+ 'prefer-const': 'error', // Use const for variables that are never reassigned
20
+ 'no-var': 'error', // Use let/const instead of var
21
+ 'prefer-arrow-callback': 'error', // Use arrow functions for callbacks
22
+ 'prefer-template': 'error', // Use template literals instead of string concatenation
23
+ 'prefer-destructuring': [
24
+ 'error',
25
+ {
26
+ array: true,
27
+ object: true
28
+ },
29
+ {
30
+ enforceForRenamedProperties: false
31
+ }
32
+ ], // Use destructuring where possible
33
+ 'prefer-rest-params': 'error', // Use rest parameters instead of arguments object
34
+ 'prefer-spread': 'error', // Use spread operator instead of .apply()
35
+ 'object-shorthand': 'error', // Use object shorthand syntax {x} instead of {x: x}
36
+ 'arrow-body-style': ['error', 'as-needed'], // Omit braces when possible in arrow functions
37
+
38
+ // Code quality
39
+ eqeqeq: ['error', 'always'], // Always use === and !== instead of == and !=
40
+ 'no-duplicate-imports': 'error', // Prevent duplicate imports from same module
41
+ 'no-useless-computed-key': 'error', // Disallow unnecessary computed property keys
42
+ 'no-useless-constructor': 'error', // Disallow unnecessary constructors
43
+ 'no-useless-rename': 'error', // Disallow renaming import/export/destructured assignments to same name
44
+ 'no-nested-ternary': 'error', // Disallow nested ternary expressions (hard to read)
45
+ 'no-unneeded-ternary': 'error', // Disallow ternary operators when simpler alternatives exist
46
+ 'prefer-object-spread': 'error', // Use object spread instead of Object.assign
47
+
48
+ // Async/Promise best practices
49
+ 'no-return-await': 'error', // Disallow unnecessary return await
50
+ 'require-await': 'error', // Disallow async functions that don't use await
51
+ 'no-promise-executor-return': 'error', // Disallow returning values from Promise executor functions
52
+
53
+ // ============================================================
54
+ // CODE QUALITY & COMPLEXITY
55
+ // Maintainability and readability rules
56
+ // Documentation: https://eslint.org/docs/rules/
57
+ // ============================================================
58
+
59
+ // Complexity (warnings to identify areas needing refactoring)
60
+ complexity: ['warn', 15], // Warn on high cyclomatic complexity
61
+ 'max-depth': ['warn', 4], // Warn on deeply nested blocks
62
+ 'max-lines': ['warn', 500], // Warn on files exceeding 500 lines
63
+ 'max-lines-per-function': [
64
+ 'warn',
65
+ {
66
+ max: 100,
67
+ skipBlankLines: true,
68
+ skipComments: true
69
+ }
70
+ ], // Warn on functions exceeding 100 lines
71
+ 'max-params': ['warn', 4], // Warn on functions with more than 4 parameters
72
+
73
+ // Comments
74
+ 'spaced-comment': [
75
+ 'error',
76
+ 'always',
77
+ {
78
+ markers: ['/']
79
+ }
80
+ ] // Require space after // or /*
81
+ }
82
+ }
@@ -0,0 +1,16 @@
1
+ import globals from 'globals'
2
+
3
+ /**
4
+ * Browser environment configuration
5
+ * Adds browser global variables (window, document, etc.)
6
+ * ECMAScript 2025 (ES2025) support
7
+ */
8
+ export default {
9
+ languageOptions: {
10
+ ecmaVersion: 2025,
11
+ sourceType: 'module',
12
+ globals: {
13
+ ...globals.browser
14
+ }
15
+ }
16
+ }
@@ -0,0 +1,21 @@
1
+ import globals from 'globals'
2
+
3
+ /**
4
+ * Node.js environment configuration
5
+ * Adds Node.js global variables (process, __dirname, require, etc.)
6
+ * ECMAScript 2025 (ES2025) support
7
+ */
8
+ export default {
9
+ languageOptions: {
10
+ ecmaVersion: 2025,
11
+ sourceType: 'module',
12
+ globals: {
13
+ ...globals.node
14
+ }
15
+ },
16
+ rules: {
17
+ // Node.js-specific rule adjustments
18
+ 'no-console': 'off', // Console is normal in Node.js
19
+ '@typescript-eslint/no-var-requires': 'off' // Allow require() in .js files
20
+ }
21
+ }
@@ -0,0 +1,18 @@
1
+ import globals from 'globals'
2
+
3
+ /**
4
+ * Universal environment configuration
5
+ * Combines both browser and Node.js globals for fullstack apps
6
+ * Useful for: Astro, Electron, fullstack monorepos
7
+ * ECMAScript 2025 (ES2025) support
8
+ */
9
+ export default {
10
+ languageOptions: {
11
+ ecmaVersion: 2025,
12
+ sourceType: 'module',
13
+ globals: {
14
+ ...globals.browser,
15
+ ...globals.node
16
+ }
17
+ }
18
+ }
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Angular configuration (basic TypeScript linting)
3
+ *
4
+ * Note: This provides basic TypeScript linting for Angular projects.
5
+ * For Angular-specific template and component rules, install:
6
+ * @angular-eslint/eslint-plugin
7
+ *
8
+ * See: https://github.com/angular-eslint/angular-eslint
9
+ */
10
+ export default function createAngularPreset() {
11
+ return [
12
+ {
13
+ files: ['**/*.ts'],
14
+ rules: {
15
+ // ============================================================
16
+ // ANGULAR-FRIENDLY TYPESCRIPT RULES
17
+ // Basic rules that work well with Angular patterns
18
+ // ============================================================
19
+
20
+ // Angular uses decorators extensively
21
+ '@typescript-eslint/no-extraneous-class': 'off',
22
+
23
+ // Angular components often have empty constructors for DI
24
+ '@typescript-eslint/no-empty-function': [
25
+ 'error',
26
+ {
27
+ allow: ['constructors']
28
+ }
29
+ ],
30
+
31
+ // Angular uses ! for definite assignment (properties set by Angular)
32
+ '@typescript-eslint/no-non-null-assertion': 'warn',
33
+
34
+ // Angular services and components use 'any' in some cases
35
+ '@typescript-eslint/no-explicit-any': 'warn',
36
+
37
+ // Parameter properties are common in Angular (constructor(private foo: Foo))
38
+ '@typescript-eslint/parameter-properties': 'off',
39
+ '@typescript-eslint/explicit-member-accessibility': 'off',
40
+
41
+ // Angular uses both interfaces and types
42
+ '@typescript-eslint/consistent-type-definitions': 'off',
43
+
44
+ // Naming conventions for Angular
45
+ '@typescript-eslint/naming-convention': [
46
+ 'error',
47
+ {
48
+ selector: 'default',
49
+ format: ['camelCase'],
50
+ leadingUnderscore: 'allow',
51
+ trailingUnderscore: 'allow'
52
+ },
53
+ {
54
+ selector: 'variable',
55
+ format: ['camelCase', 'UPPER_CASE', 'PascalCase'],
56
+ leadingUnderscore: 'allow'
57
+ },
58
+ {
59
+ selector: 'typeLike',
60
+ format: ['PascalCase']
61
+ },
62
+ {
63
+ selector: 'enumMember',
64
+ format: ['PascalCase', 'UPPER_CASE']
65
+ },
66
+ {
67
+ selector: 'property',
68
+ format: null // Allow any format for properties (Angular templates use various patterns)
69
+ }
70
+ ]
71
+ }
72
+ }
73
+ ]
74
+ }
@@ -0,0 +1,38 @@
1
+ import { configs } from 'eslint-plugin-astro'
2
+
3
+ /**
4
+ * Astro framework configuration
5
+ * Rules for Astro components and island architecture
6
+ *
7
+ * Rules organized by category:
8
+ * - Component best practices
9
+ * - Island architecture
10
+ * - Template syntax
11
+ * - Accessibility
12
+ */
13
+ export default function createAstroPreset() {
14
+ return [
15
+ ...configs.recommended,
16
+ ...configs['jsx-a11y-recommended'],
17
+ {
18
+ files: ['**/*.astro'],
19
+ rules: {
20
+ // Component Best Practices (5 rules)
21
+ 'astro/no-conflict-set-directives': 'error', // Avoid conflicting set directives
22
+ 'astro/no-unused-define-vars-in-style': 'error', // Remove unused CSS variables
23
+ 'astro/no-deprecated-astro-canonicalurl': 'error', // Use new canonical URL API
24
+ 'astro/no-deprecated-astro-fetchcontent': 'error', // Use new content collections
25
+ 'astro/no-deprecated-astro-resolve': 'error', // Use new module resolution
26
+
27
+ // Template Syntax (4 rules)
28
+ 'astro/valid-compile': 'error', // Ensure valid Astro syntax
29
+ 'astro/no-set-html-directive': 'warn', // Warn about XSS risk
30
+ 'astro/semi': ['error', 'always'], // Consistent semicolons in frontmatter
31
+ 'astro/prefer-class-list-directive': 'error' // Use class:list over className
32
+
33
+ // Accessibility (included from jsx-a11y-recommended preset)
34
+ // - alt-text, click-events-have-key-events, etc.
35
+ }
36
+ }
37
+ ]
38
+ }
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Node.js backend configuration
3
+ * Conservative rules for Node.js/Express/Fastify backend services
4
+ */
5
+ export default function createNodePreset() {
6
+ return [
7
+ {
8
+ files: ['**/*.js', '**/*.ts', '**/*.mjs'],
9
+ rules: {
10
+ // ============================================================
11
+ // NODE.JS BACKEND RULES
12
+ // Best practices for server-side JavaScript/TypeScript
13
+ // ============================================================
14
+
15
+ // Console usage is normal in Node.js
16
+ 'no-console': 'off',
17
+
18
+ // Process and __dirname are standard in Node
19
+ 'no-process-env': 'off',
20
+ 'no-process-exit': 'warn',
21
+
22
+ // Async patterns
23
+ 'no-async-promise-executor': 'error',
24
+ 'require-atomic-updates': 'error',
25
+
26
+ // Error handling
27
+ 'no-throw-literal': 'error',
28
+ 'prefer-promise-reject-errors': 'error',
29
+
30
+ // Node.js specific
31
+ 'callback-return': 'off', // Modern Node uses async/await
32
+ 'handle-callback-err': 'off', // Modern Node uses async/await
33
+ 'no-mixed-requires': 'off', // ES modules don't have this issue
34
+ 'no-new-require': 'error',
35
+ 'no-path-concat': 'error', // Use path.join() instead
36
+
37
+ // Security
38
+ 'no-eval': 'error',
39
+ 'no-implied-eval': 'error',
40
+ 'no-new-func': 'error',
41
+
42
+ // Best practices for backend
43
+ 'no-unused-vars': [
44
+ 'error',
45
+ {
46
+ args: 'after-used',
47
+ argsIgnorePattern: '^_',
48
+ varsIgnorePattern: '^_'
49
+ }
50
+ ],
51
+
52
+ // Allow both require and import
53
+ '@typescript-eslint/no-var-requires': 'off'
54
+ }
55
+ }
56
+ ]
57
+ }
@@ -0,0 +1,76 @@
1
+ import react from 'eslint-plugin-react'
2
+ import reactHooks from 'eslint-plugin-react-hooks'
3
+
4
+ /**
5
+ * React configuration (conservative)
6
+ * Includes React + React Hooks plugins with essential rules
7
+ */
8
+ export default function createReactPreset() {
9
+ return [
10
+ // React recommended configuration
11
+ react.configs.flat.recommended,
12
+ react.configs.flat['jsx-runtime'], // Disable React-in-scope for React 17+
13
+
14
+ // React Hooks rules
15
+ {
16
+ files: ['**/*.js', '**/*.jsx', '**/*.ts', '**/*.tsx'],
17
+ plugins: {
18
+ 'react-hooks': reactHooks
19
+ },
20
+ rules: reactHooks.configs.recommended.rules
21
+ },
22
+
23
+ // Custom opinionated React rules
24
+ {
25
+ files: ['**/*.js', '**/*.jsx', '**/*.ts', '**/*.tsx'],
26
+ settings: {
27
+ react: {
28
+ version: 'detect' // Automatically detect React version
29
+ }
30
+ },
31
+ rules: {
32
+ // ============================================================
33
+ // REACT RULES (Conservative - Essential Only)
34
+ // React best practices for modern React 17+
35
+ // Documentation: https://github.com/jsx-eslint/eslint-plugin-react
36
+ // ============================================================
37
+
38
+ // Modern React (17+) adjustments
39
+ 'react/react-in-jsx-scope': 'off', // Not needed in React 17+ with new JSX transform
40
+ 'react/jsx-uses-react': 'off', // Not needed in React 17+ with new JSX transform
41
+
42
+ // TypeScript integration
43
+ 'react/prop-types': 'off', // TypeScript handles prop validation
44
+
45
+ // JSX best practices
46
+ 'react/jsx-uses-vars': 'error', // Prevent variables used in JSX being marked as unused
47
+ 'react/jsx-curly-brace-presence': ['error', { props: 'never', children: 'never' }], // Use strings when possible: prop="value" not prop={"value"}
48
+ 'react/self-closing-comp': 'error', // Use <Component /> instead of <Component></Component>
49
+ 'react/jsx-boolean-value': ['error', 'never'], // Use prop instead of prop={true}
50
+ 'react/jsx-fragments': ['error', 'syntax'], // Use <> instead of <Fragment>
51
+ 'react/jsx-no-useless-fragment': 'error', // Disallow unnecessary fragments
52
+
53
+ // Component definition
54
+ 'react/function-component-definition': [
55
+ 'error',
56
+ {
57
+ namedComponents: 'arrow-function', // const Component = () => ...
58
+ unnamedComponents: 'arrow-function'
59
+ }
60
+ ],
61
+
62
+ // Hooks (enforced by react-hooks plugin)
63
+ // - react-hooks/rules-of-hooks: error
64
+ // - react-hooks/exhaustive-deps: warn
65
+
66
+ // Best practices
67
+ 'react/no-array-index-key': 'warn', // Warn when using array index as key (can cause issues)
68
+ 'react/jsx-key': 'error', // Require key prop in iterators
69
+ 'react/no-children-prop': 'error', // Prevent passing children as props
70
+ 'react/no-danger': 'warn', // Warn on dangerouslySetInnerHTML (XSS risk)
71
+ 'react/no-deprecated': 'error', // Prevent usage of deprecated methods
72
+ 'react/no-unknown-property': 'error' // Prevent usage of unknown DOM properties
73
+ }
74
+ }
75
+ ]
76
+ }