UNPKG

9.43 kBJavaScriptView Raw
1const fs = require('fs')
2const { resolve } = require('path')
3
4const {
5 isNgAvailable,
6 isSrcDirAvailable,
7 isSrcAppDirAvailable,
8 isWebpackAvailable,
9 magicNumbers,
10 tryFile,
11 webpackSpecVars,
12} = require('./_util')
13
14const BABEL_CONFIG = resolve('babel.config.js')
15const BABEL_RC_CONFIG = resolve('.babelrc.js')
16
17let configFile
18
19try {
20 configFile =
21 tryFile(BABEL_CONFIG) ||
22 tryFile(BABEL_RC_CONFIG) ||
23 require.resolve('@1stg/babel-preset/config')
24} catch (e) {}
25
26exports.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
49const TS_CONFIGS = [
50 tryFile(resolve('tsconfig.eslint.json')) ||
51 tryFile(resolve('tsconfig.base.json')) ||
52 tryFile(resolve('tsconfig.json')),
53].filter(Boolean)
54
55let project
56
57try {
58 project = TS_CONFIGS.length ? TS_CONFIGS : require.resolve('@1stg/tsconfig')
59} catch (e) {}
60
61const 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
89const 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, // TypeScript itself has handle this
189 'node/shebang': 0,
190 // @typescript-eslint/no-floating-promises has already handled there case
191 'promise/always-return': 0,
192 'promise/catch-or-return': 0,
193 },
194}
195
196exports.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
245exports.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
257let tslint = false
258
259try {
260 tslint = !!require.resolve('tslint')
261} catch (e) {}
262
263const TSLINT_CONFIG = resolve('tslint.json')
264const tslintConfigAvailable = fs.existsSync(TSLINT_CONFIG)
265
266let lintFile = tslintConfigAvailable ? TSLINT_CONFIG : undefined
267
268try {
269 lintFile = lintFile || require.resolve('@1stg/tslint-config')
270} catch (e) {}
271
272exports.tslint = {
273 files: '*.{ts,tsx}',
274 excludedFiles: '*.d.ts',
275 plugins: tslintConfigAvailable ? ['@typescript-eslint/tslint'] : undefined,
276 rules: Object.assign(
277 {
278 // `ordered-imports` of tslint is better for now
279 'import/order': 0,
280 },
281 tslintConfigAvailable || {
282 '@typescript-eslint/tslint/config': [
283 2,
284 {
285 lintFile,
286 },
287 ],
288 },
289 ),
290}
291
292exports.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
307const reactJsx = {
308 extends: [
309 'standard-jsx', // for Vue
310 'standard-react',
311 'plugin:react/recommended',
312 'prettier',
313 'prettier/react',
314 ],
315 settings: {
316 react: {
317 version: 'detect',
318 },
319 },
320}
321
322exports.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
347exports.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
356exports.reactTs = {
357 files: '*.{ts,tsx}',
358 rules: {
359 'no-restricted-imports': [2, 'prop-types'],
360 'react/prop-types': 0,
361 },
362}
363
364exports.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
373exports.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
379const nonSourceRules = {
380 'node/no-extraneous-import': 0,
381 'node/no-extraneous-require': 0,
382 'node/no-unsupported-features/es-builtins': 0,
383}
384
385exports.test = {
386 files: '**/{__test__,test,tests}/**/*.{js,jsx,mdx,ts,tsx,vue}',
387 rules: nonSourceRules,
388}
389
390exports.jest = {
391 files: '*.{spec,test}.{js,jsx,ts,tsx}',
392 extends: ['plugin:jest/recommended'],
393 rules: exports.test.rules,
394}
395
396exports.stories = {
397 files: '**/stories/**/*.{js,jsx,mdx,ts,tsx,vue}',
398 rules: nonSourceRules,
399}
400
401exports.config = {
402 files: ['.*rc.js', '*.config.{js,ts}'],
403 rules: nonSourceRules,
404}
405
406exports.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)