Skip to content

Commit fad1cf4

Browse files
committed
chore: migrate away from kcd-scripts
1 parent 0ff8904 commit fad1cf4

20 files changed

+463
-81
lines changed

.github/ISSUE_TEMPLATE.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ learn how: http://kcd.im/pull-request
1818
Relevant code or config
1919

2020
```javascript
21+
2122
```
2223

2324
What you did:

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ node_modules
22
coverage
33
dist
44
.DS_Store
5+
.jest-cache
56

67
# these cause more harm than good
78
# when working with contributors

.husky/pre-commit

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
npx lint-staged

.huskyrc.js

Lines changed: 0 additions & 1 deletion
This file was deleted.

.prettierrc.js

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,21 @@
1-
module.exports = require('kcd-scripts/prettier')
1+
/** @type {import('prettier').Options} */
2+
module.exports = {
3+
arrowParens: 'avoid',
4+
bracketSameLine: false,
5+
bracketSpacing: false,
6+
embeddedLanguageFormatting: 'auto',
7+
endOfLine: 'lf',
8+
htmlWhitespaceSensitivity: 'css',
9+
insertPragma: false,
10+
jsxSingleQuote: false,
11+
printWidth: 80,
12+
proseWrap: 'always',
13+
quoteProps: 'as-needed',
14+
requirePragma: false,
15+
semi: false,
16+
singleAttributePerLine: false,
17+
singleQuote: true,
18+
tabWidth: 2,
19+
trailingComma: 'all',
20+
useTabs: false,
21+
}

babel.config.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
module.exports = {
2+
presets: [
3+
['@babel/preset-env', {targets: {node: 'current'}}],
4+
'@babel/preset-typescript',
5+
],
6+
}

eslint.config.js

Lines changed: 330 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,330 @@
1+
const eslintPluginImport = require('eslint-plugin-import')
2+
const eslintPluginJest = require('eslint-plugin-jest')
3+
const eslintPluginJestDom = require('eslint-plugin-jest-dom')
4+
const tseslint = require('typescript-eslint')
5+
const eslintConfigPrettier = require('eslint-config-prettier')
6+
7+
module.exports = tseslint.config(
8+
// Global ignores
9+
{
10+
ignores: ['node_modules', 'coverage', 'dist', 'types/__tests__'],
11+
},
12+
13+
// Base config for all JavaScript/TypeScript files
14+
{
15+
files: ['**/*.{js,jsx,ts,tsx}'],
16+
languageOptions: {
17+
ecmaVersion: 2020,
18+
sourceType: 'module',
19+
globals: {
20+
// Browser globals
21+
window: 'readonly',
22+
document: 'readonly',
23+
navigator: 'readonly',
24+
console: 'readonly',
25+
// Node.js globals
26+
process: 'readonly',
27+
__dirname: 'readonly',
28+
__filename: 'readonly',
29+
module: 'readonly',
30+
require: 'readonly',
31+
exports: 'readonly',
32+
Buffer: 'readonly',
33+
// ES6+ globals
34+
Promise: 'readonly',
35+
Set: 'readonly',
36+
Map: 'readonly',
37+
},
38+
},
39+
plugins: {
40+
import: eslintPluginImport,
41+
},
42+
rules: {
43+
// ESLint core rules (based on kentcdodds config)
44+
'accessor-pairs': 'error',
45+
'array-callback-return': 'error',
46+
'arrow-body-style': 'off',
47+
'block-scoped-var': 'error',
48+
camelcase: 'off',
49+
complexity: ['error', 20],
50+
'consistent-return': 'error',
51+
'consistent-this': 'off',
52+
'constructor-super': 'error',
53+
curly: ['error', 'multi-line'],
54+
'default-case': 'error',
55+
'default-case-last': 'error',
56+
'dot-notation': 'error',
57+
eqeqeq: 'off',
58+
'for-direction': 'error',
59+
'func-name-matching': 'error',
60+
'func-names': 'error',
61+
'getter-return': ['error', {allowImplicit: true}],
62+
'guard-for-in': 'error',
63+
'id-denylist': 'error',
64+
'id-match': ['error', '^\\$?(__)?(([A-Z]|[a-z]|[0-9]+)|([A-Z_]))*\\$?$'],
65+
'max-depth': ['error', 4],
66+
'max-lines': ['error', {max: 2500, skipBlankLines: false}],
67+
'max-nested-callbacks': ['error', 7],
68+
'max-params': ['error', 7],
69+
'max-statements-per-line': ['error', {max: 1}],
70+
'new-cap': 'error',
71+
'no-alert': 'error',
72+
'no-array-constructor': 'error',
73+
'no-async-promise-executor': 'off',
74+
'no-await-in-loop': 'error',
75+
'no-bitwise': 'error',
76+
'no-caller': 'error',
77+
'no-case-declarations': 'error',
78+
'no-class-assign': 'error',
79+
'no-compare-neg-zero': 'error',
80+
'no-cond-assign': 'error',
81+
'no-console': 'off',
82+
'no-const-assign': 'error',
83+
'no-constant-binary-expression': 'error',
84+
'no-constant-condition': 'error',
85+
'no-constructor-return': 'error',
86+
'no-control-regex': 'error',
87+
'no-debugger': 'error',
88+
'no-delete-var': 'error',
89+
'no-div-regex': 'error',
90+
'no-dupe-args': 'error',
91+
'no-dupe-class-members': 'error',
92+
'no-dupe-else-if': 'error',
93+
'no-dupe-keys': 'error',
94+
'no-duplicate-case': 'error',
95+
'no-duplicate-imports': 'error',
96+
'no-else-return': 'off',
97+
'no-empty': 'error',
98+
'no-empty-character-class': 'error',
99+
'no-empty-pattern': 'error',
100+
'no-eval': 'error',
101+
'no-extend-native': 'error',
102+
'no-extra-bind': 'error',
103+
'no-fallthrough': 'error',
104+
'no-func-assign': 'error',
105+
'no-global-assign': 'error',
106+
'no-implicit-coercion': 'off',
107+
'no-implied-eval': 'error',
108+
'no-import-assign': 'error',
109+
'no-invalid-this': 'off',
110+
'no-irregular-whitespace': 'error',
111+
'no-iterator': 'error',
112+
'no-labels': 'error',
113+
'no-lone-blocks': 'error',
114+
'no-loop-func': 'error',
115+
'no-loss-of-precision': 'error',
116+
'no-misleading-character-class': 'error',
117+
'no-multi-assign': 'off',
118+
'no-multi-str': 'error',
119+
'no-new': 'error',
120+
'no-new-func': 'error',
121+
'no-new-native-nonconstructor': 'error',
122+
'no-new-wrappers': 'error',
123+
'no-obj-calls': 'error',
124+
'no-octal': 'error',
125+
'no-octal-escape': 'error',
126+
'no-param-reassign': 'off',
127+
'no-proto': 'error',
128+
'no-redeclare': 'error',
129+
'no-regex-spaces': 'error',
130+
'no-return-assign': ['error', 'except-parens'],
131+
'no-return-await': 'error',
132+
'no-script-url': 'error',
133+
'no-self-assign': 'error',
134+
'no-self-compare': 'error',
135+
'no-sequences': 'error',
136+
'no-shadow': 'off',
137+
'no-shadow-restricted-names': 'error',
138+
'no-sparse-arrays': 'error',
139+
'no-this-before-super': 'error',
140+
'no-throw-literal': 'error',
141+
'no-undef': 'error',
142+
'no-undef-init': 'error',
143+
'no-unexpected-multiline': 'error',
144+
'no-unmodified-loop-condition': 'error',
145+
'no-unneeded-ternary': 'error',
146+
'no-unreachable': 'error',
147+
'no-unsafe-finally': 'error',
148+
'no-unsafe-negation': 'error',
149+
'no-unsafe-optional-chaining': 'error',
150+
'no-unused-expressions': 'error',
151+
'no-unused-labels': 'error',
152+
'no-unused-vars': [
153+
'error',
154+
{
155+
argsIgnorePattern: '^_',
156+
varsIgnorePattern: '^_',
157+
caughtErrorsIgnorePattern: '^_',
158+
},
159+
],
160+
'no-use-before-define': 'off',
161+
'no-useless-backreference': 'error',
162+
'no-useless-call': 'error',
163+
'no-useless-catch': 'off',
164+
'no-useless-concat': 'error',
165+
'no-useless-constructor': 'off',
166+
'no-useless-escape': 'error',
167+
'no-useless-return': 'error',
168+
'no-var': 'error',
169+
'no-void': 'off',
170+
'no-with': 'error',
171+
'object-shorthand': 'off',
172+
'one-var': ['error', 'never'],
173+
'prefer-arrow-callback': ['error', {allowNamedFunctions: true}],
174+
'prefer-const': 'error',
175+
'prefer-promise-reject-errors': 'error',
176+
'prefer-rest-params': 'error',
177+
'prefer-spread': 'error',
178+
'prefer-template': 'off',
179+
radix: 'error',
180+
'require-await': 'off',
181+
'require-yield': 'error',
182+
'use-isnan': 'error',
183+
'valid-typeof': 'error',
184+
185+
// Import plugin rules
186+
'import/consistent-type-specifier-style': ['error', 'prefer-inline'],
187+
'import/default': 'error',
188+
'import/export': 'error',
189+
'import/first': 'error',
190+
'import/named': 'error',
191+
'import/namespace': 'error',
192+
'import/no-absolute-path': 'error',
193+
'import/no-amd': 'error',
194+
'import/no-duplicates': 'error',
195+
'import/no-empty-named-blocks': 'error',
196+
'import/no-extraneous-dependencies': 'error',
197+
'import/no-mutable-exports': 'error',
198+
'import/no-named-as-default': 'error',
199+
'import/no-named-as-default-member': 'error',
200+
'import/no-named-default': 'error',
201+
'import/no-self-import': 'error',
202+
'import/no-webpack-loader-syntax': 'error',
203+
'import/order': [
204+
'warn',
205+
{
206+
groups: [
207+
'builtin',
208+
['external', 'internal'],
209+
'parent',
210+
['sibling', 'index'],
211+
],
212+
},
213+
],
214+
},
215+
},
216+
217+
// TypeScript files
218+
...tseslint.configs.recommended.map(config => ({
219+
...config,
220+
files: ['**/*.ts', '**/*.tsx'],
221+
})),
222+
{
223+
files: ['**/*.ts', '**/*.tsx'],
224+
rules: {
225+
// Disable JS rules that conflict with TS
226+
'no-undef': 'off', // TypeScript handles this
227+
'no-unused-vars': 'off', // Use TypeScript version instead
228+
'@typescript-eslint/no-unused-vars': [
229+
'error',
230+
{
231+
argsIgnorePattern: '^_',
232+
varsIgnorePattern: '^_',
233+
caughtErrorsIgnorePattern: '^_',
234+
},
235+
],
236+
},
237+
},
238+
239+
// TypeScript definition files
240+
{
241+
files: ['**/*.d.ts'],
242+
rules: {
243+
'@typescript-eslint/no-empty-interface': 'off',
244+
'@typescript-eslint/no-empty-object-type': 'off',
245+
'@typescript-eslint/no-explicit-any': 'off',
246+
'@typescript-eslint/no-unused-vars': 'off',
247+
'@typescript-eslint/triple-slash-reference': 'off',
248+
},
249+
},
250+
251+
// Test files
252+
{
253+
files: [
254+
'src/__tests__/**/*.{js,jsx,ts,tsx}',
255+
'tests/**/*.{js,jsx,ts,tsx}',
256+
'**/*.{spec,test}.{js,jsx,ts,tsx}',
257+
],
258+
plugins: {
259+
jest: eslintPluginJest,
260+
'jest-dom': eslintPluginJestDom,
261+
},
262+
languageOptions: {
263+
globals: {
264+
...eslintPluginJest.environments.globals.globals,
265+
global: 'readonly', // Node.js global
266+
},
267+
},
268+
rules: {
269+
// Test-specific rule overrides
270+
'max-lines-per-function': 'off',
271+
272+
// Jest rules
273+
'jest/max-nested-describe': 'error',
274+
'jest/no-commented-out-tests': 'warn',
275+
'jest/no-conditional-expect': 'error',
276+
'jest/no-conditional-in-test': 'error',
277+
'jest/no-deprecated-functions': 'error',
278+
'jest/no-disabled-tests': 'warn',
279+
'jest/no-done-callback': 'error',
280+
'jest/no-export': 'error',
281+
'jest/no-focused-tests': 'error',
282+
'jest/no-identical-title': 'error',
283+
'jest/no-interpolation-in-snapshots': 'error',
284+
'jest/no-large-snapshots': ['warn', {maxSize: 300}],
285+
'jest/no-mocks-import': 'error',
286+
'jest/no-test-prefixes': 'error',
287+
'jest/prefer-called-with': 'error',
288+
'jest/prefer-comparison-matcher': 'error',
289+
'jest/prefer-each': 'error',
290+
'jest/prefer-equality-matcher': 'error',
291+
'jest/prefer-hooks-in-order': 'error',
292+
'jest/prefer-hooks-on-top': 'error',
293+
'jest/prefer-mock-promise-shorthand': 'error',
294+
'jest/prefer-snapshot-hint': 'error',
295+
'jest/prefer-to-contain': 'warn',
296+
'jest/prefer-to-have-length': 'warn',
297+
'jest/prefer-todo': 'warn',
298+
'jest/valid-describe-callback': 'error',
299+
'jest/valid-expect': 'error',
300+
'jest/valid-expect-in-promise': 'error',
301+
'jest/valid-title': 'warn',
302+
303+
// jest-dom rules
304+
'jest-dom/prefer-checked': 'error',
305+
'jest-dom/prefer-empty': 'error',
306+
'jest-dom/prefer-enabled-disabled': 'error',
307+
'jest-dom/prefer-focus': 'error',
308+
'jest-dom/prefer-in-document': 'error',
309+
'jest-dom/prefer-required': 'error',
310+
'jest-dom/prefer-to-have-attribute': 'error',
311+
'jest-dom/prefer-to-have-class': 'error',
312+
'jest-dom/prefer-to-have-style': 'error',
313+
'jest-dom/prefer-to-have-text-content': 'error',
314+
'jest-dom/prefer-to-have-value': 'error',
315+
},
316+
},
317+
318+
// Files that use Jest globals outside of test files
319+
{
320+
files: ['src/index.js', 'tests/setup-env.js'],
321+
languageOptions: {
322+
globals: {
323+
...eslintPluginJest.environments.globals.globals,
324+
},
325+
},
326+
},
327+
328+
// Disable Prettier-conflicting rules (must be last)
329+
eslintConfigPrettier,
330+
)

0 commit comments

Comments
 (0)