UNPKG

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