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