@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.
- package/LICENSE +21 -0
- package/README.md +646 -0
- package/bin/setup-tool-config.js +675 -0
- package/package.json +168 -0
- package/src/detectors.js +261 -0
- package/src/index.js +64 -0
- package/src/tools/eslint/index.js +287 -0
- package/src/tools/eslint/presets/base.js +82 -0
- package/src/tools/eslint/presets/environments/browser.js +16 -0
- package/src/tools/eslint/presets/environments/node.js +21 -0
- package/src/tools/eslint/presets/environments/universal.js +18 -0
- package/src/tools/eslint/presets/frameworks/angular.js +74 -0
- package/src/tools/eslint/presets/frameworks/astro.js +38 -0
- package/src/tools/eslint/presets/frameworks/node.js +57 -0
- package/src/tools/eslint/presets/frameworks/react.js +76 -0
- package/src/tools/eslint/presets/frameworks/solid.js +45 -0
- package/src/tools/eslint/presets/frameworks/svelte.js +78 -0
- package/src/tools/eslint/presets/frameworks/vanilla.js +16 -0
- package/src/tools/eslint/presets/frameworks/vue.js +125 -0
- package/src/tools/eslint/presets/imports.js +41 -0
- package/src/tools/eslint/presets/typescript.js +131 -0
- package/src/tools/prettier/README.md +398 -0
- package/src/tools/prettier/index.js +114 -0
- package/src/tools/prettier/presets/base.js +36 -0
- package/src/tools/prettier/presets/frameworks/astro.js +15 -0
- package/src/tools/prettier/presets/frameworks/react.js +15 -0
- package/src/tools/prettier/presets/frameworks/svelte.js +22 -0
- package/src/tools/prettier/presets/frameworks/vanilla.js +13 -0
- package/src/tools/prettier/presets/frameworks/vue.js +20 -0
- package/src/tools/prettier/presets/prettierignore.js +56 -0
- package/src/tools/semantic-release/CI_SETUP.md +66 -0
- package/src/tools/semantic-release/README.md +533 -0
- package/src/tools/semantic-release/index.js +130 -0
- package/src/tools/semantic-release/presets/default.js +37 -0
- package/src/tools/semantic-release/presets/library.js +58 -0
- package/src/tools/semantic-release/presets/monorepo.js +48 -0
- package/src/tools/semantic-release/templates/.gitlab-ci.yml +85 -0
- package/src/tools/semantic-release/templates/bitbucket-pipelines.yml +100 -0
- package/src/tools/semantic-release/templates/github-workflow.yml +107 -0
- package/src/tools/stylelint/README.md +425 -0
- package/src/tools/stylelint/index.js +191 -0
- package/src/tools/stylelint/presets/base.js +50 -0
- package/src/tools/stylelint/presets/css-modules.js +43 -0
- package/src/tools/stylelint/presets/frameworks/react.js +18 -0
- package/src/tools/stylelint/presets/frameworks/svelte.js +28 -0
- package/src/tools/stylelint/presets/frameworks/vanilla.js +14 -0
- package/src/tools/stylelint/presets/frameworks/vue.js +38 -0
- package/src/tools/stylelint/presets/scss.js +83 -0
- package/src/tools/stylelint/presets/tailwind.js +49 -0
- 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
|
+
}
|