code-quality-lib 2.0.1 → 2.5.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.
@@ -0,0 +1,87 @@
1
+ # Quality reports and configuration
2
+ .quality-report.md
3
+ .code-quality/
4
+
5
+ # Build outputs
6
+ dist/
7
+ build/
8
+ .next/
9
+ out/
10
+
11
+ # Dependencies
12
+ node_modules/
13
+
14
+ # Logs
15
+ *.log
16
+ npm-debug.log*
17
+ yarn-debug.log*
18
+ yarn-error.log*
19
+
20
+ # Runtime data
21
+ pids
22
+ *.pid
23
+ *.seed
24
+ *.pid.lock
25
+
26
+ # Coverage directory used by tools like istanbul
27
+ coverage/
28
+ *.lcov
29
+
30
+ # nyc test coverage
31
+ .nyc_output
32
+
33
+ # Dependency directories
34
+ jspm_packages/
35
+
36
+ # Optional npm cache directory
37
+ .npm
38
+
39
+ # Optional eslint cache
40
+ .eslintcache
41
+
42
+ # Optional REPL history
43
+ .node_repl_history
44
+
45
+ # Output of 'npm pack'
46
+ *.tgz
47
+
48
+ # Yarn Integrity file
49
+ .yarn-integrity
50
+
51
+ # dotenv environment variables file
52
+ .env
53
+ .env.test
54
+ .env.local
55
+ .env.development.local
56
+ .env.test.local
57
+ .env.production.local
58
+
59
+ # parcel-bundler cache (https://parceljs.org/)
60
+ .cache
61
+ .parcel-cache
62
+
63
+ # next.js build output
64
+ .next
65
+
66
+ # nuxt.js build output
67
+ .nuxt
68
+
69
+ # vuepress build output
70
+ .vuepress/dist
71
+
72
+ # Serverless directories
73
+ .serverless
74
+
75
+ # FuseBox cache
76
+ .fusebox/
77
+
78
+ # DynamoDB Local files
79
+ .dynamodb/
80
+
81
+ # TernJS port file
82
+ .tern-port
83
+
84
+ # Stores VSCode versions used for testing VSCode extensions
85
+ .vscode-test
86
+
87
+ .venv
@@ -0,0 +1,17 @@
1
+ {
2
+ "semi": false,
3
+ "trailingComma": "es5",
4
+ "singleQuote": true,
5
+ "printWidth": 100,
6
+ "tabWidth": 2,
7
+ "useTabs": false,
8
+ "endOfLine": "lf",
9
+ "arrowParens": "always",
10
+ "bracketSpacing": true,
11
+ "bracketSameLine": false,
12
+ "quoteProps": "as-needed",
13
+ "jsxSingleQuote": true,
14
+ "proseWrap": "preserve",
15
+ "htmlWhitespaceSensitivity": "css",
16
+ "embeddedLanguageFormatting": "auto"
17
+ }
@@ -0,0 +1,32 @@
1
+ # Code Quality Configuration
2
+
3
+ This directory contains reference configuration files for code quality tools.
4
+
5
+ ## Files
6
+
7
+ - **eslint.config.mjs** - ESLint flat config with React, TypeScript, and accessibility rules
8
+ - **tsconfig.json** - TypeScript configuration with strict settings
9
+ - **.prettierrc** - Prettier formatting rules
10
+ - **.prettierrcignore** - Files to ignore when formatting
11
+ - **knip.json** - Dead code detection configuration
12
+
13
+ ## Usage
14
+
15
+ These files are automatically copied to your project's `.code-quality/` directory when you run:
16
+
17
+ ```bash
18
+ code-quality --init
19
+ # or
20
+ code-quality --wizard
21
+ ```
22
+
23
+ ## Customization
24
+
25
+ You can modify these files after copying them to suit your project's needs.
26
+
27
+ ## Notes
28
+
29
+ - ESLint config uses conditional loading for optional plugins (Next.js, jsx-a11y, prettier)
30
+ - TypeScript config is optimized for React/Next.js projects
31
+ - Prettier config matches ESLint semicolon settings
32
+ - Knip config is set to ignore test files and dependencies
@@ -0,0 +1,34 @@
1
+ {
2
+ "version": "1.0.0",
3
+ "packageManager": "npm",
4
+ "useProjectConfig": false,
5
+ "loadEnv": true,
6
+ "generated": "2026-03-11T16:57:59.790Z",
7
+ "environments": {
8
+ "development": {
9
+ "tools": [
10
+ "ESLint",
11
+ "TypeScript",
12
+ "Prettier"
13
+ ]
14
+ },
15
+ "ci": {
16
+ "tools": [
17
+ "ESLint",
18
+ "TypeScript",
19
+ "Prettier",
20
+ "Knip",
21
+ "Snyk"
22
+ ]
23
+ },
24
+ "production": {
25
+ "tools": [
26
+ "ESLint",
27
+ "TypeScript",
28
+ "Prettier",
29
+ "Knip",
30
+ "Snyk"
31
+ ]
32
+ }
33
+ }
34
+ }
@@ -0,0 +1,311 @@
1
+ import js from '@eslint/js'
2
+ import typescript from '@typescript-eslint/eslint-plugin'
3
+ import tsParser from '@typescript-eslint/parser'
4
+ import prettier from 'eslint-config-prettier'
5
+ import importPlugin from 'eslint-plugin-import'
6
+ import react from 'eslint-plugin-react'
7
+ import reactHooks from 'eslint-plugin-react-hooks'
8
+ import sonarjs from 'eslint-plugin-sonarjs'
9
+ import unicorn from 'eslint-plugin-unicorn'
10
+
11
+ // Import optional plugins - these may or may not be installed
12
+ let nextPlugin
13
+ let jsxA11yPlugin
14
+ let prettierPlugin
15
+
16
+ try {
17
+ const nextModule = await import('eslint-plugin-next')
18
+ nextPlugin = nextModule.default || nextModule
19
+ } catch {
20
+ // Next.js plugin not installed, skip Next.js rules
21
+ }
22
+
23
+ try {
24
+ const jsxA11yModule = await import('eslint-plugin-jsx-a11y')
25
+ jsxA11yPlugin = jsxA11yModule.default || jsxA11yModule
26
+ } catch {
27
+ // jsx-a11y plugin not installed, skip accessibility rules
28
+ }
29
+
30
+ try {
31
+ const prettierModule = await import('eslint-plugin-prettier')
32
+ prettierPlugin = prettierModule.default || prettierModule
33
+ } catch {
34
+ // eslint-plugin-prettier not installed, skip prettier rules
35
+ }
36
+
37
+ const eslintConfig = [
38
+ {
39
+ ignores: [
40
+ 'node_modules/',
41
+ '.pnp',
42
+ '.pnp.js',
43
+ '.next/',
44
+ 'out/',
45
+ 'dist/',
46
+ 'build/',
47
+ '.env*',
48
+ '*.log',
49
+ 'pids',
50
+ '*.pid',
51
+ '*.seed',
52
+ '*.pid.lock',
53
+ 'coverage/',
54
+ '.nyc_output',
55
+ '.cache/',
56
+ '.parcel-cache/',
57
+ '*.tsbuildinfo',
58
+ '.DS_Store',
59
+ '.DS_Store?',
60
+ '._*',
61
+ '.Spotlight-V100',
62
+ '.Trashes',
63
+ 'ehthumbs.db',
64
+ 'Thumbs.db',
65
+ '.vscode/',
66
+ '.idea/',
67
+ 'tmp/',
68
+ 'temp/',
69
+ '*.tmp',
70
+ '*.temp',
71
+ 'public/',
72
+ '.code-quality/',
73
+ '**/.code-quality/**', // More specific pattern
74
+ 'eslint.config.mjs',
75
+ 'next.config.ts',
76
+ '.venv/',
77
+ ],
78
+ },
79
+ js.configs.recommended,
80
+ {
81
+ files: ['**/*.{js,jsx,ts,tsx}'],
82
+ languageOptions: {
83
+ parser: tsParser,
84
+ parserOptions: {
85
+ ecmaVersion: 'latest',
86
+ sourceType: 'module',
87
+ ecmaFeatures: {
88
+ jsx: true,
89
+ },
90
+ project: './tsconfig.json',
91
+ tsconfigRootDir: import.meta.dirname,
92
+ },
93
+ globals: {
94
+ console: 'readonly',
95
+ process: 'readonly',
96
+ __dirname: 'readonly',
97
+ module: 'readonly',
98
+ require: 'readonly',
99
+ // Browser globals
100
+ window: 'readonly',
101
+ document: 'readonly',
102
+ fetch: 'readonly',
103
+ setTimeout: 'readonly',
104
+ clearTimeout: 'readonly',
105
+ setInterval: 'readonly',
106
+ clearInterval: 'readonly',
107
+ requestAnimationFrame: 'readonly',
108
+ URL: 'readonly',
109
+ URLSearchParams: 'readonly',
110
+ FormData: 'readonly',
111
+ HeadersInit: 'readonly',
112
+ RequestInit: 'readonly',
113
+ TextEncoder: 'readonly',
114
+ btoa: 'readonly',
115
+ crypto: 'readonly',
116
+ sessionStorage: 'readonly',
117
+ // React globals
118
+ React: 'readonly',
119
+ // DOM types
120
+ HTMLDivElement: 'readonly',
121
+ // Node.js globals
122
+ Buffer: 'readonly',
123
+ // Type globals
124
+ Item: 'readonly',
125
+ Bundle: 'readonly',
126
+ ConstStallCategory: 'readonly',
127
+ },
128
+ },
129
+ settings: {
130
+ 'import/resolver': {
131
+ typescript: {
132
+ alwaysTryTypes: true,
133
+ project: './tsconfig.json',
134
+ },
135
+ },
136
+ },
137
+ plugins: {
138
+ '@typescript-eslint': typescript,
139
+ react,
140
+ 'react-hooks': reactHooks,
141
+ sonarjs,
142
+ unicorn,
143
+ import: importPlugin,
144
+ ...(nextPlugin ? { '@next/next': nextPlugin } : {}),
145
+ ...(jsxA11yPlugin ? { 'jsx-a11y': jsxA11yPlugin } : {}),
146
+ ...(prettierPlugin ? { prettier: prettierPlugin } : {}),
147
+ },
148
+ rules: {
149
+ // React
150
+ 'react/jsx-no-literals': 'off',
151
+ 'react/prop-types': 'off',
152
+ 'react/self-closing-comp': 'warn',
153
+ 'react/jsx-sort-props': [
154
+ 'warn',
155
+ {
156
+ callbacksLast: true,
157
+ shorthandFirst: true,
158
+ noSortAlphabetically: false,
159
+ reservedFirst: true,
160
+ },
161
+ ],
162
+ 'react/jsx-fragments': ['warn', 'syntax'],
163
+ 'react/jsx-no-useless-fragment': 'warn',
164
+ 'react/jsx-pascal-case': 'warn',
165
+ 'react/no-array-index-key': 'warn',
166
+ 'react/react-in-jsx-scope': 'off',
167
+ // JSX quotes consistency with Prettier jsxSingleQuote: true
168
+ 'jsx-quotes': ['error', 'prefer-single'],
169
+
170
+ // TypeScript
171
+ '@typescript-eslint/no-explicit-any': 'warn',
172
+ '@typescript-eslint/no-require-imports': 'off',
173
+ '@typescript-eslint/no-unused-vars': [
174
+ 'warn',
175
+ {
176
+ args: 'after-used',
177
+ ignoreRestSiblings: false,
178
+ argsIgnorePattern: '^_.*$',
179
+ },
180
+ ],
181
+ '@typescript-eslint/explicit-function-return-type': 'off',
182
+ '@typescript-eslint/explicit-module-boundary-types': 'off',
183
+ '@typescript-eslint/no-empty-interface': 'warn',
184
+ '@typescript-eslint/no-non-null-assertion': 'warn',
185
+ '@typescript-eslint/prefer-as-const': 'warn',
186
+
187
+ // Next.js (if available)
188
+ ...(nextPlugin
189
+ ? {
190
+ '@next/next/no-html-link-for-pages': 'off',
191
+ '@next/next/no-img-element': 'warn',
192
+ '@next/next/no-sync-scripts': 'warn',
193
+ }
194
+ : {}),
195
+
196
+ // Accessibility (if jsx-a11y plugin available)
197
+ ...(jsxA11yPlugin
198
+ ? {
199
+ 'jsx-a11y/alt-text': 'warn',
200
+ 'jsx-a11y/interactive-supports-focus': 'off',
201
+ 'jsx-a11y/click-events-have-key-events': 'warn',
202
+ 'jsx-a11y/no-static-element-interactions': 'warn',
203
+ }
204
+ : {}),
205
+
206
+ // Import ordering
207
+ 'import/order': [
208
+ 'error',
209
+ {
210
+ groups: [
211
+ 'type',
212
+ 'builtin',
213
+ 'external',
214
+ 'internal',
215
+ 'parent',
216
+ 'sibling',
217
+ 'index',
218
+ 'object',
219
+ ],
220
+ pathGroups: [
221
+ {
222
+ pattern: '~/**',
223
+ group: 'external',
224
+ position: 'after',
225
+ },
226
+ ],
227
+ pathGroupsExcludedImportTypes: ['builtin'],
228
+ 'newlines-between': 'always',
229
+ alphabetize: {
230
+ order: 'asc',
231
+ caseInsensitive: true,
232
+ },
233
+ },
234
+ ],
235
+ 'import/no-duplicates': 'error',
236
+ 'import/no-unresolved': 'error',
237
+ 'import/no-cycle': 'error',
238
+
239
+ // Code quality
240
+ 'no-console': ['error', { allow: ['warn', 'error'] }],
241
+ ...(prettierPlugin
242
+ ? {
243
+ 'prettier/prettier': [
244
+ 'error',
245
+ {
246
+ endOfLine: 'auto',
247
+ },
248
+ ],
249
+ }
250
+ : {}),
251
+ 'padding-line-between-statements': [
252
+ 'warn',
253
+ { blankLine: 'always', prev: '*', next: 'return' },
254
+ { blankLine: 'always', prev: ['const', 'let', 'var'], next: '*' },
255
+ {
256
+ blankLine: 'any',
257
+ prev: ['const', 'let', 'var'],
258
+ next: ['const', 'let', 'var'],
259
+ },
260
+ ],
261
+
262
+ 'react-hooks/exhaustive-deps': 'warn',
263
+ 'react-hooks/rules-of-hooks': 'error',
264
+ 'no-param-reassign': 'warn',
265
+ 'no-return-await': 'warn',
266
+ 'prefer-const': 'warn',
267
+ 'no-var': 'error',
268
+ eqeqeq: ['error', 'always'],
269
+ 'no-unused-expressions': 'error',
270
+ // Semicolons consistency with Prettier semi: false
271
+ semi: ['error', 'never'],
272
+
273
+ // SonarJS
274
+ 'sonarjs/cognitive-complexity': ['error', 15],
275
+ 'sonarjs/no-duplicate-string': 'warn',
276
+
277
+ // Unicorn
278
+ 'unicorn/no-array-for-each': 'error',
279
+ 'unicorn/prefer-node-protocol': 'error',
280
+ },
281
+ },
282
+ {
283
+ files: ['**/*.{js,jsx,ts,tsx}'],
284
+ rules: {
285
+ 'no-restricted-syntax': [
286
+ 'error',
287
+ {
288
+ selector:
289
+ "MemberExpression[object.object.name='process'][object.property.name='env'][property.type='Identifier'][property.name=/^NEXT_PUBLIC_/]",
290
+ message:
291
+ 'Do not access process.env.NEXT_PUBLIC_* directly. Use src/constants/environment.ts instead.',
292
+ },
293
+ {
294
+ selector:
295
+ "MemberExpression[object.object.name='process'][object.property.name='env'][property.type='Literal'][property.value=/^NEXT_PUBLIC_/]",
296
+ message:
297
+ 'Do not access process.env.NEXT_PUBLIC_* directly. Use src/constants/environment.ts instead.',
298
+ },
299
+ ],
300
+ },
301
+ },
302
+ {
303
+ files: ['src/constants/environment.ts'],
304
+ rules: {
305
+ 'no-restricted-syntax': 'off',
306
+ },
307
+ },
308
+ prettier,
309
+ ]
310
+
311
+ export default eslintConfig
@@ -0,0 +1,30 @@
1
+ {
2
+ "entry": ["index.js"],
3
+ "project": ["*.js"],
4
+ "ignore": [
5
+ "node_modules/**",
6
+ "dist/**",
7
+ "build/**",
8
+ "coverage/**",
9
+ "*.config.js",
10
+ "*.config.ts",
11
+ "test/**",
12
+ "**/*.test.*",
13
+ "**/*.spec.*",
14
+ "examples/**",
15
+ ".code-quality/**",
16
+ "**/*.d.ts"
17
+ ],
18
+ "ignoreBinaries": ["code-quality"],
19
+ "ignoreDependencies": [
20
+ "eslint-plugin-*",
21
+ "@typescript-eslint/*",
22
+ "@eslint/js",
23
+ "prettier",
24
+ "@types/*",
25
+ "typescript",
26
+ "knip",
27
+ "snyk",
28
+ "dotenv"
29
+ ]
30
+ }
@@ -0,0 +1,32 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "lib": ["dom", "dom.iterable", "esnext"],
5
+ "allowJs": true,
6
+ "skipLibCheck": true,
7
+ "strict": true,
8
+ "noUncheckedIndexedAccess": true,
9
+ "noImplicitOverride": true,
10
+ "noPropertyAccessFromIndexSignature": true,
11
+ "useUnknownInCatchVariables": true,
12
+ "noEmit": true,
13
+ "esModuleInterop": true,
14
+ "module": "ESNext",
15
+ "moduleResolution": "bundler",
16
+ "resolveJsonModule": true,
17
+ "isolatedModules": true,
18
+ "jsx": "react-jsx",
19
+ "incremental": true,
20
+ "forceConsistentCasingInFileNames": true,
21
+ "baseUrl": ".",
22
+ "paths": {
23
+ "@/*": ["src/*"]
24
+ }
25
+ },
26
+ "include": [
27
+ "**/*.ts",
28
+ "**/*.tsx",
29
+ "**/*.mts"
30
+ ],
31
+ "exclude": ["node_modules", "dist", "build", "coverage", "examples"]
32
+ }