1 |
|
2 | const { resolve } = require('path')
|
3 |
|
4 | const {
|
5 | isAngularAvailable,
|
6 | isReactAvailable,
|
7 | isPkgAvailable,
|
8 | isTsAvailable,
|
9 | isVueAvailable,
|
10 | tryFile,
|
11 | tryPkg,
|
12 | } = require('@pkgr/utils')
|
13 |
|
14 | const { camelCaseRule, magicNumbers } = require('./_util')
|
15 |
|
16 | const configFile =
|
17 | tryFile(resolve('babel.config.js')) ||
|
18 | tryFile(resolve('.babelrc.js')) ||
|
19 | tryPkg('@1stg/babel-preset/config')
|
20 |
|
21 | const jsBase = {
|
22 | files: '*.{mjs,js,jsx}',
|
23 | parser: 'babel-eslint',
|
24 | parserOptions: configFile && {
|
25 | babelOptions: {
|
26 | configFile,
|
27 | },
|
28 | },
|
29 | plugins: ['babel'],
|
30 | extends: ['prettier/babel'],
|
31 | rules: {
|
32 | camelcase: 0,
|
33 | 'new-cap': 0,
|
34 | 'no-invalid-this': 0,
|
35 | 'no-unused-expressions': 0,
|
36 | 'valid-typeof': 0,
|
37 | 'babel/camelcase': [
|
38 | 2,
|
39 | {
|
40 | properties: 'never',
|
41 | ignoreDestructuring: true,
|
42 | },
|
43 | ],
|
44 | 'babel/new-cap': 2,
|
45 | 'babel/no-invalid-this': 2,
|
46 | 'babel/no-unused-expressions': 2,
|
47 | 'babel/valid-typeof': 2,
|
48 | },
|
49 | }
|
50 |
|
51 | exports.js = jsBase
|
52 |
|
53 | const project =
|
54 | tryFile(resolve('tsconfig.eslint.json')) ||
|
55 | tryFile(resolve('tsconfig.base.json')) ||
|
56 | tryFile(resolve('tsconfig.json')) ||
|
57 | tryPkg('@1stg/tsconfig')
|
58 |
|
59 | const resolveSettings = {
|
60 | 'import/external-module-folders': [
|
61 | 'node_modules',
|
62 | 'node_modules/@d-ts',
|
63 | 'node_modules/@types',
|
64 | ],
|
65 | 'import/resolver': {
|
66 | ts: {
|
67 | alwaysTryTypes: true,
|
68 | directory: project,
|
69 | },
|
70 | },
|
71 | node: {
|
72 | resolvePaths: [
|
73 | tryFile('node_modules/@d-ts', true),
|
74 | tryFile('node_modules/@types', true),
|
75 | ].filter(Boolean),
|
76 | tryExtensions: [
|
77 | '.ts',
|
78 | '.tsx',
|
79 | '.d.ts',
|
80 | '.vue',
|
81 | '.mjs',
|
82 | '.js',
|
83 | '.jsx',
|
84 | '.json',
|
85 | '.node',
|
86 | '.mdx',
|
87 | ],
|
88 | },
|
89 | }
|
90 |
|
91 | const tsBase = {
|
92 | files: '*.{ts,tsx}',
|
93 | extends: [
|
94 | 'plugin:@typescript-eslint/eslint-recommended',
|
95 | 'plugin:@typescript-eslint/recommended',
|
96 | 'plugin:import/typescript',
|
97 | 'prettier/@typescript-eslint',
|
98 | ],
|
99 | settings: resolveSettings,
|
100 | rules: {
|
101 | '@typescript-eslint/adjacent-overload-signatures': 2,
|
102 | '@typescript-eslint/array-type': [
|
103 | 2,
|
104 | {
|
105 | default: 'array-simple',
|
106 | },
|
107 | ],
|
108 | '@typescript-eslint/ban-ts-ignore': 0,
|
109 | '@typescript-eslint/camelcase': camelCaseRule,
|
110 | '@typescript-eslint/consistent-type-definitions': [2, 'interface'],
|
111 | '@typescript-eslint/explicit-function-return-type': 0,
|
112 | '@typescript-eslint/explicit-member-accessibility': [
|
113 | 2,
|
114 | {
|
115 | accessibility: 'no-public',
|
116 | overrides: {
|
117 | parameterProperties: 'off',
|
118 | },
|
119 | },
|
120 | ],
|
121 | '@typescript-eslint/member-naming': [
|
122 | 2,
|
123 | {
|
124 | private: '^_',
|
125 | },
|
126 | ],
|
127 | '@typescript-eslint/member-ordering': 2,
|
128 | '@typescript-eslint/no-empty-function': 2,
|
129 | '@typescript-eslint/no-extraneous-class': 2,
|
130 | '@typescript-eslint/no-for-in-array': 2,
|
131 | '@typescript-eslint/no-non-null-assertion': 0,
|
132 | '@typescript-eslint/no-parameter-properties': 0,
|
133 | '@typescript-eslint/no-require-imports': 2,
|
134 | '@typescript-eslint/no-this-alias': [
|
135 | 2,
|
136 | {
|
137 | allowDestructuring: true,
|
138 | allowedNames: ['self'],
|
139 | },
|
140 | ],
|
141 | '@typescript-eslint/no-type-alias': [
|
142 | 2,
|
143 | {
|
144 | allowAliases: 'in-unions-and-intersections',
|
145 | allowCallbacks: 'always',
|
146 | allowLiterals: 'in-unions-and-intersections',
|
147 | allowMappedTypes: 'always',
|
148 | },
|
149 | ],
|
150 | '@typescript-eslint/no-use-before-define': [
|
151 | 2,
|
152 | {
|
153 | classes: false,
|
154 | functions: false,
|
155 | },
|
156 | ],
|
157 | '@typescript-eslint/no-useless-constructor': 2,
|
158 | '@typescript-eslint/no-unused-vars': [
|
159 | 2,
|
160 | {
|
161 | argsIgnorePattern: '^_',
|
162 | },
|
163 | ],
|
164 | '@typescript-eslint/prefer-for-of': 2,
|
165 | '@typescript-eslint/prefer-function-type': 2,
|
166 | '@typescript-eslint/triple-slash-reference': [
|
167 | 2,
|
168 | {
|
169 | lib: 'never',
|
170 | path: 'always',
|
171 | types: 'prefer-import',
|
172 | },
|
173 | ],
|
174 | '@typescript-eslint/unified-signatures': 2,
|
175 | 'import/default': 0,
|
176 | 'import/named': 0,
|
177 | 'import/no-duplicates': 2,
|
178 | 'import/no-named-as-default': 0,
|
179 | 'import/no-named-as-default-member': 0,
|
180 | 'no-empty-function': 0,
|
181 | 'no-unused-vars': 0,
|
182 | 'no-useless-constructor': 0,
|
183 | 'node/no-missing-import': 0,
|
184 | 'node/shebang': 0,
|
185 |
|
186 | 'promise/always-return': 0,
|
187 | 'promise/catch-or-return': 0,
|
188 | },
|
189 | }
|
190 |
|
191 | exports.ts = [
|
192 | tsBase,
|
193 | {
|
194 | files: '{bin,cli}.ts',
|
195 | rules: {
|
196 | 'node/shebang': 0,
|
197 | },
|
198 | },
|
199 | {
|
200 | files: '*.{ts,tsx}',
|
201 | excludedFiles: '*.d.ts',
|
202 | parserOptions: {
|
203 | project,
|
204 | },
|
205 | extends: ['plugin:@typescript-eslint/recommended-requiring-type-checking'],
|
206 | rules: {
|
207 | '@typescript-eslint/no-floating-promises': [
|
208 | 2,
|
209 | {
|
210 | ignoreVoid: true,
|
211 | },
|
212 | ],
|
213 | '@typescript-eslint/no-magic-numbers': [
|
214 | 2,
|
215 | {
|
216 | enforceConst: true,
|
217 | ignore: magicNumbers,
|
218 | ignoreArrayIndexes: true,
|
219 | ignoreEnums: true,
|
220 | ignoreNumericLiteralTypes: true,
|
221 | ignoreReadonlyClassProperties: true,
|
222 | },
|
223 | ],
|
224 | '@typescript-eslint/no-unnecessary-condition': [
|
225 | 2,
|
226 | {
|
227 | ignoreRhs: true,
|
228 | },
|
229 | ],
|
230 | '@typescript-eslint/no-unnecessary-qualifier': 2,
|
231 | '@typescript-eslint/no-unnecessary-type-arguments': 2,
|
232 | '@typescript-eslint/prefer-readonly': 2,
|
233 | '@typescript-eslint/restrict-plus-operands': 2,
|
234 | 'no-constant-condition': 0,
|
235 | 'no-magic-numbers': 0,
|
236 | },
|
237 | },
|
238 | ]
|
239 |
|
240 | exports.dTs = {
|
241 | files: '*.d.ts',
|
242 | rules: {
|
243 | '@typescript-eslint/no-explicit-any': 0,
|
244 | '@typescript-eslint/no-extraneous-class': 0,
|
245 | '@typescript-eslint/no-namespace': 0,
|
246 | '@typescript-eslint/no-unused-vars': 0,
|
247 | 'import/no-duplicates': 0,
|
248 | 'import/order': 0,
|
249 | 'node/no-extraneous-import': 0,
|
250 | },
|
251 | }
|
252 |
|
253 | const TSLINT_CONFIG = tryFile(resolve('tslint.json'))
|
254 | const lintFile = TSLINT_CONFIG || tryPkg('@1stg/tslint-config')
|
255 |
|
256 | exports.tslint = {
|
257 | files: '*.{ts,tsx}',
|
258 | excludedFiles: '*.d.ts',
|
259 | plugins: TSLINT_CONFIG ? ['@typescript-eslint/tslint'] : undefined,
|
260 | rules: Object.assign(
|
261 | {
|
262 |
|
263 | 'import/order': 0,
|
264 | },
|
265 | TSLINT_CONFIG
|
266 | ? undefined
|
267 | : {
|
268 | '@typescript-eslint/tslint/config': [
|
269 | 2,
|
270 | {
|
271 | lintFile,
|
272 | },
|
273 | ],
|
274 | },
|
275 | ),
|
276 | }
|
277 |
|
278 | exports.angular = [
|
279 | {
|
280 | files: '*.ts',
|
281 | rules: {
|
282 | '@typescript-eslint/member-naming': 0,
|
283 | },
|
284 | },
|
285 | {
|
286 | files: ['*.component.ts', '*.module.ts', 'component.ts', 'module.ts'],
|
287 | rules: {
|
288 | '@typescript-eslint/no-extraneous-class': 0,
|
289 | },
|
290 | },
|
291 | ]
|
292 |
|
293 | const reactJsx = {
|
294 | extends: [
|
295 | 'standard-react',
|
296 | 'plugin:react/recommended',
|
297 | 'prettier',
|
298 | 'prettier/react',
|
299 | ],
|
300 | settings: {
|
301 | react: {
|
302 | version: 'detect',
|
303 | },
|
304 | },
|
305 | }
|
306 |
|
307 | exports.react = [
|
308 | Object.assign(
|
309 | {
|
310 | files: '*.{js,jsx,tsx}',
|
311 | rules: {
|
312 | 'react/jsx-boolean-value': [2, 'always'],
|
313 | 'react/jsx-handler-names': [
|
314 | 2,
|
315 | {
|
316 | eventHandlerPrefix: false,
|
317 | eventHandlerPropPrefix: 'on',
|
318 | },
|
319 | ],
|
320 | },
|
321 | },
|
322 | reactJsx,
|
323 | ),
|
324 | {
|
325 | files: '*.tsx',
|
326 | rules: {
|
327 | 'react/display-name': 0,
|
328 | },
|
329 | },
|
330 | ]
|
331 |
|
332 | exports.reactHooks = {
|
333 | files: '*.{js,jsx,ts,tsx}',
|
334 | plugins: ['react-hooks'],
|
335 | rules: {
|
336 | 'react-hooks/rules-of-hooks': 2,
|
337 | 'react-hooks/exhaustive-deps': 2,
|
338 | },
|
339 | }
|
340 |
|
341 | exports.reactTs = {
|
342 | files: '*.{ts,tsx}',
|
343 | rules: {
|
344 | 'no-restricted-imports': [2, 'prop-types'],
|
345 | 'react/prop-types': 0,
|
346 | },
|
347 | }
|
348 |
|
349 | const vueExtends = ['plugin:vue/recommended', 'prettier', 'prettier/vue']
|
350 |
|
351 | exports.vue = [
|
352 | Object.assign({}, jsBase, {
|
353 | parser: 'vue-eslint-parser',
|
354 | parserOptions: Object.assign({}, jsBase.parserOptions, {
|
355 | parser: jsBase.parser,
|
356 | }),
|
357 | extends: vueExtends,
|
358 | }),
|
359 | Object.assign({}, tsBase, {
|
360 | parser: 'vue-eslint-parser',
|
361 | files: '*.{vue,ts,tsx}',
|
362 | parserOptions: {
|
363 | parser: '@typescript-eslint/parser',
|
364 | extraFileExtensions: ['.vue'],
|
365 | },
|
366 | extends: tsBase.extends.concat(vueExtends),
|
367 | }),
|
368 | ]
|
369 |
|
370 | exports.mdx = {
|
371 | files: '*.{md,mdx}',
|
372 | extends: reactJsx.extends.concat('plugin:mdx/recommended'),
|
373 | parserOptions: jsBase.parserOptions,
|
374 | settings: Object.assign({}, reactJsx.settings, resolveSettings),
|
375 | }
|
376 |
|
377 | const nonSourceRules = {
|
378 | 'node/no-extraneous-import': 0,
|
379 | 'node/no-extraneous-require': 0,
|
380 | 'node/no-unsupported-features/es-builtins': 0,
|
381 | }
|
382 |
|
383 | exports.test = {
|
384 | files: '**/{__test__,test,tests}/**/*.{js,jsx,mdx,ts,tsx,vue}',
|
385 | rules: nonSourceRules,
|
386 | }
|
387 |
|
388 | exports.jest = {
|
389 | files: '*.{spec,test}.{js,jsx,ts,tsx}',
|
390 | extends: ['plugin:jest/recommended'],
|
391 | rules: exports.test.rules,
|
392 | }
|
393 |
|
394 | exports.stories = {
|
395 | files: '**/stories/**/*.{js,jsx,mdx,ts,tsx,vue}',
|
396 | rules: nonSourceRules,
|
397 | }
|
398 |
|
399 | exports.config = {
|
400 | files: ['.*rc.js', '*.config.{js,ts}'],
|
401 | rules: nonSourceRules,
|
402 | }
|
403 |
|
404 | exports.overrides = []
|
405 | .concat(
|
406 | isPkgAvailable('@babel/core') && exports.js,
|
407 | isTsAvailable && exports.ts,
|
408 | isPkgAvailable('tslint') && lintFile && exports.tslint,
|
409 | isReactAvailable && exports.react,
|
410 | isReactAvailable && exports.reactHooks,
|
411 | isReactAvailable && exports.reactTs,
|
412 | isVueAvailable && exports.vue,
|
413 | isAngularAvailable && exports.angular,
|
414 | exports.mdx,
|
415 | exports.jest,
|
416 | exports.test,
|
417 | exports.stories,
|
418 | exports.config,
|
419 | exports.dTs,
|
420 | )
|
421 | .filter(Boolean)
|