UNPKG

9.61 kBJavaScriptView Raw
1/* eslint-disable sonarjs/no-duplicate-string */
2const { resolve } = require('path')
3
4const {
5 isAngularAvailable,
6 isReactAvailable,
7 isPkgAvailable,
8 isTsAvailable,
9 isVueAvailable,
10 tryFile,
11 tryPkg,
12} = require('@pkgr/utils')
13
14const { camelCaseRule, magicNumbers } = require('./_util')
15
16const configFile =
17 tryFile(resolve('babel.config.js')) ||
18 tryFile(resolve('.babelrc.js')) ||
19 tryPkg('@1stg/babel-preset/config')
20
21const 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
51exports.js = jsBase
52
53const project =
54 tryFile(resolve('tsconfig.eslint.json')) ||
55 tryFile(resolve('tsconfig.base.json')) ||
56 tryFile(resolve('tsconfig.json')) ||
57 tryPkg('@1stg/tsconfig')
58
59const 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
91const 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, // TypeScript itself has handle this
184 'node/shebang': 0,
185 // @typescript-eslint/no-floating-promises has already handled there case
186 'promise/always-return': 0,
187 'promise/catch-or-return': 0,
188 },
189}
190
191exports.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
240exports.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
253const TSLINT_CONFIG = tryFile(resolve('tslint.json'))
254const lintFile = TSLINT_CONFIG || tryPkg('@1stg/tslint-config')
255
256exports.tslint = {
257 files: '*.{ts,tsx}',
258 excludedFiles: '*.d.ts',
259 plugins: TSLINT_CONFIG ? ['@typescript-eslint/tslint'] : undefined,
260 rules: Object.assign(
261 {
262 // `ordered-imports` of tslint is better for now
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
278exports.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
293const 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
307exports.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
332exports.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
341exports.reactTs = {
342 files: '*.{ts,tsx}',
343 rules: {
344 'no-restricted-imports': [2, 'prop-types'],
345 'react/prop-types': 0,
346 },
347}
348
349const vueExtends = ['plugin:vue/recommended', 'prettier', 'prettier/vue']
350
351exports.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
370exports.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
377const nonSourceRules = {
378 'node/no-extraneous-import': 0,
379 'node/no-extraneous-require': 0,
380 'node/no-unsupported-features/es-builtins': 0,
381}
382
383exports.test = {
384 files: '**/{__test__,test,tests}/**/*.{js,jsx,mdx,ts,tsx,vue}',
385 rules: nonSourceRules,
386}
387
388exports.jest = {
389 files: '*.{spec,test}.{js,jsx,ts,tsx}',
390 extends: ['plugin:jest/recommended'],
391 rules: exports.test.rules,
392}
393
394exports.stories = {
395 files: '**/stories/**/*.{js,jsx,mdx,ts,tsx,vue}',
396 rules: nonSourceRules,
397}
398
399exports.config = {
400 files: ['.*rc.js', '*.config.{js,ts}'],
401 rules: nonSourceRules,
402}
403
404exports.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)