eslint-plugin-smarthr 6.13.0 → 6.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -0
- package/package.json +5 -6
- package/rules/require-barrel-import/README.md +174 -0
- package/rules/require-barrel-import/barrel-purity-checker.js +58 -0
- package/rules/require-barrel-import/index.js +23 -1
- package/test/require-barrel-import.js +358 -0
- package/.claude/settings.local.json +0 -127
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
|
4
4
|
|
|
5
|
+
## [6.14.0](https://github.com/kufu/tamatebako/compare/eslint-plugin-smarthr-v6.13.0...eslint-plugin-smarthr-v6.14.0) (2026-05-13)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### Features
|
|
9
|
+
|
|
10
|
+
* **require-barrel-import:** バレルファイルの純粋性チェックを追加 ([#1271](https://github.com/kufu/tamatebako/issues/1271)) ([99c16ab](https://github.com/kufu/tamatebako/commit/99c16abc2c7aacedceafdc89df7ab6d8eda9eeb4))
|
|
11
|
+
|
|
5
12
|
## [6.13.0](https://github.com/kufu/tamatebako/compare/eslint-plugin-smarthr-v6.12.1...eslint-plugin-smarthr-v6.13.0) (2026-04-20)
|
|
6
13
|
|
|
7
14
|
|
package/package.json
CHANGED
|
@@ -1,13 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-plugin-smarthr",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.14.0",
|
|
4
4
|
"author": "SmartHR",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"description": "A sharable ESLint plugin for SmartHR",
|
|
7
7
|
"main": "index.js",
|
|
8
|
-
"scripts": {
|
|
9
|
-
"test": "jest"
|
|
10
|
-
},
|
|
11
8
|
"repository": {
|
|
12
9
|
"type": "git",
|
|
13
10
|
"url": "git+git@github.com:kufu/tamatebako.git"
|
|
@@ -34,5 +31,7 @@
|
|
|
34
31
|
"eslintplugin",
|
|
35
32
|
"smarthr"
|
|
36
33
|
],
|
|
37
|
-
"
|
|
38
|
-
|
|
34
|
+
"scripts": {
|
|
35
|
+
"test": "jest"
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -67,6 +67,180 @@ import { buttonUtils } from '../utils' // OK
|
|
|
67
67
|
import { Button } from '@/components/Button' // OK
|
|
68
68
|
```
|
|
69
69
|
|
|
70
|
+
## バレルファイルの純粋性チェック
|
|
71
|
+
|
|
72
|
+
バレルファイル(index.ts、client.ts等)は**設置されたディレクトリ外へのexportが責務**です。それ以外の実装(import文、変数定義、関数定義など)は禁止されます。
|
|
73
|
+
|
|
74
|
+
### なぜ純粋性が必要なのか
|
|
75
|
+
|
|
76
|
+
バレルファイルの責務はディレクトリ外部へのexport(公開API定義)のみです。ロジックや定義を含むと、以下の問題が発生します:
|
|
77
|
+
|
|
78
|
+
1. **責務の混在**: エクスポート定義とロジック実装が混在し、ファイルの役割が不明確になる
|
|
79
|
+
2. **メンテナンス性の低下**: バレルファイルが肥大化し、何をexportしているか把握しづらくなる
|
|
80
|
+
3. **テスト困難**: ロジックはテスト対象であるべきだが、バレル内に書くとテストしづらい
|
|
81
|
+
4. **分割の妨げ**: 実装はそれぞれ専用ファイルに分離すべき
|
|
82
|
+
|
|
83
|
+
### ❌ 禁止されるパターン
|
|
84
|
+
|
|
85
|
+
```typescript
|
|
86
|
+
// ❌ import文の使用
|
|
87
|
+
import { Button } from './Button'
|
|
88
|
+
|
|
89
|
+
// ❌ 変数定義
|
|
90
|
+
const DEFAULT_SIZE = 'medium'
|
|
91
|
+
export const sizes = ['small', 'medium', 'large']
|
|
92
|
+
|
|
93
|
+
// ❌ 関数定義
|
|
94
|
+
function helper() {
|
|
95
|
+
return 'value'
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// ❌ export function
|
|
99
|
+
export function createConfig() {
|
|
100
|
+
return { theme: 'light' }
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// ❌ クラス定義
|
|
104
|
+
class Util {}
|
|
105
|
+
export class Helper {}
|
|
106
|
+
|
|
107
|
+
// ❌ 型定義
|
|
108
|
+
export type Size = 'small' | 'medium' | 'large'
|
|
109
|
+
export interface ComponentAPI {
|
|
110
|
+
render: () => void
|
|
111
|
+
}
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### ✅ 許可されるパターン
|
|
115
|
+
|
|
116
|
+
```typescript
|
|
117
|
+
// ✅ re-export(named export)
|
|
118
|
+
export { Button } from './Button'
|
|
119
|
+
export { Input, TextArea } from './Input'
|
|
120
|
+
|
|
121
|
+
// ✅ TypeScript型のre-export
|
|
122
|
+
export type { ButtonProps } from './Button'
|
|
123
|
+
export type { Size, ComponentAPI } from './types'
|
|
124
|
+
|
|
125
|
+
// ✅ default exportのre-export
|
|
126
|
+
export { default } from './Component' // default → default
|
|
127
|
+
export { default as Button } from './Button' // default → named
|
|
128
|
+
export { Button as default } from './Button' // named → default
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
#### 💡 Tips: default exportのre-export
|
|
132
|
+
|
|
133
|
+
バレルファイルで default export を扱う場合、以下の3つのパターンがあります:
|
|
134
|
+
|
|
135
|
+
```typescript
|
|
136
|
+
// パターン1: default → default
|
|
137
|
+
// Component.tsx が export default Component している場合
|
|
138
|
+
export { default } from './Component'
|
|
139
|
+
// → このバレルからも default として再エクスポート
|
|
140
|
+
|
|
141
|
+
// パターン2: default → named
|
|
142
|
+
// Component.tsx が export default Component している場合
|
|
143
|
+
export { default as Component } from './Component'
|
|
144
|
+
// → default を Component という名前で再エクスポート
|
|
145
|
+
|
|
146
|
+
// パターン3: named → default
|
|
147
|
+
// Button.tsx が export const Button = ... している場合
|
|
148
|
+
export { Button as default } from './Button'
|
|
149
|
+
// → named export の Button を default として再エクスポート
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
**重要:** バレルファイル内で `export default` を直接記述することはできません。常に `from` 句を使った re-export である必要があります。
|
|
153
|
+
|
|
154
|
+
```typescript
|
|
155
|
+
// ❌ 禁止: バレルファイル内で直接 export default
|
|
156
|
+
const Component = () => { ... }
|
|
157
|
+
export default Component
|
|
158
|
+
|
|
159
|
+
// ✅ 許可: 別ファイルから re-export
|
|
160
|
+
export { Component as default } from './Component'
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
### 正しい実装方法
|
|
164
|
+
|
|
165
|
+
ロジックや定義が必要な場合は、専用ファイルを作成してそこからre-exportします:
|
|
166
|
+
|
|
167
|
+
```typescript
|
|
168
|
+
// ❌ 悪い例: index.ts内で定義
|
|
169
|
+
// components/Button/index.ts
|
|
170
|
+
export const DEFAULT_SIZE = 'medium'
|
|
171
|
+
export type Size = 'small' | 'medium' | 'large'
|
|
172
|
+
export { Button } from './Button'
|
|
173
|
+
|
|
174
|
+
// ✅ 良い例: 専用ファイルを作成
|
|
175
|
+
// components/Button/constants.ts
|
|
176
|
+
export const DEFAULT_SIZE = 'medium'
|
|
177
|
+
|
|
178
|
+
// components/Button/types.ts
|
|
179
|
+
export type Size = 'small' | 'medium' | 'large'
|
|
180
|
+
|
|
181
|
+
// components/Button/index.ts
|
|
182
|
+
export { Button } from './Button'
|
|
183
|
+
export { DEFAULT_SIZE } from './constants'
|
|
184
|
+
export type { Size } from './types'
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
### よくあるパターンと修正方法
|
|
188
|
+
|
|
189
|
+
#### 複数ファイルからimportしてマージする設定ファイル
|
|
190
|
+
|
|
191
|
+
以下のようなパターンもバレルファイルの純粋性チェックに引っかかります:
|
|
192
|
+
|
|
193
|
+
```typescript
|
|
194
|
+
// ❌ エラーになる: index.ts内で複数ファイルをマージ
|
|
195
|
+
// config/index.ts
|
|
196
|
+
import a from './a'
|
|
197
|
+
import b from './b'
|
|
198
|
+
import c from './c'
|
|
199
|
+
|
|
200
|
+
export const config = {
|
|
201
|
+
...a,
|
|
202
|
+
...b,
|
|
203
|
+
...c,
|
|
204
|
+
}
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
**なぜ禁止?**
|
|
208
|
+
- このパターンは依存解決時にマージ処理が発生するため、副作用を持つロジックと言える
|
|
209
|
+
- バレルファイルは単なる「export の窓口」であるべきで、ロジックを持つべきではない
|
|
210
|
+
|
|
211
|
+
**修正方法1: 個別にexport(推奨)**
|
|
212
|
+
|
|
213
|
+
```typescript
|
|
214
|
+
// ✅ 基本: 個別にre-export
|
|
215
|
+
// config/index.ts
|
|
216
|
+
export { default as a } from './a'
|
|
217
|
+
export { default as b } from './b'
|
|
218
|
+
export { default as c } from './c'
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
利用側で必要なものだけimportできるため、この方法が最も推奨されます。
|
|
222
|
+
|
|
223
|
+
**修正方法2: どうしてもマージしたい場合**
|
|
224
|
+
|
|
225
|
+
オブジェクト形式でまとめてexportする必要がある場合は、eslint-disableコメントで対応:
|
|
226
|
+
|
|
227
|
+
```typescript
|
|
228
|
+
// config/index.ts
|
|
229
|
+
/* eslint-disable smarthr/require-barrel-import -- 設定ファイルのマージのため */
|
|
230
|
+
import a from './a'
|
|
231
|
+
import b from './b'
|
|
232
|
+
import c from './c'
|
|
233
|
+
|
|
234
|
+
export const config = {
|
|
235
|
+
...a,
|
|
236
|
+
...b,
|
|
237
|
+
...c,
|
|
238
|
+
}
|
|
239
|
+
/* eslint-enable smarthr/require-barrel-import */
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
ただし、この場合はindex.tsが「バレルファイル」ではなく「設定ファイル」としての責務を持つことになるため、ディレクトリ名やファイル名の見直しも検討してください。
|
|
243
|
+
|
|
70
244
|
## config
|
|
71
245
|
|
|
72
246
|
### 必須設定
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
const path = require('path')
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* バレルファイル名のパターンにマッチするかチェック
|
|
5
|
+
* @param {string} filePath - ファイルパス
|
|
6
|
+
* @param {Array<string>} barrelFileNames - バレルファイル名のリスト(index, client, server等)
|
|
7
|
+
* @returns {boolean}
|
|
8
|
+
*/
|
|
9
|
+
const isBarrelFile = (filePath, barrelFileNames) => {
|
|
10
|
+
const fileName = path.basename(filePath, path.extname(filePath))
|
|
11
|
+
return barrelFileNames.includes(fileName)
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* バレルファイルの純粋性をチェックするビジター
|
|
16
|
+
* バレルファイルは re-export のみを行うべきで、以下は禁止:
|
|
17
|
+
* - import文
|
|
18
|
+
* - 変数定義(const, let, var)
|
|
19
|
+
* - 関数定義(export function含む)
|
|
20
|
+
* - クラス定義(export class含む)
|
|
21
|
+
*
|
|
22
|
+
* @param {object} context - ESLintコンテキスト
|
|
23
|
+
* @param {Array<string>} barrelFileNames - バレルファイル名のリスト
|
|
24
|
+
* @returns {object} ビジターオブジェクト
|
|
25
|
+
*/
|
|
26
|
+
const createBarrelPurityVisitor = (context, barrelFileNames) => {
|
|
27
|
+
// このファイルがバレルファイルでなければチェックしない
|
|
28
|
+
if (!isBarrelFile(context.filename, barrelFileNames)) {
|
|
29
|
+
return {}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// エラー報告の共通処理
|
|
33
|
+
const reportPurityError = (node) => {
|
|
34
|
+
context.report({
|
|
35
|
+
node,
|
|
36
|
+
message: `バレルファイルは設置されたディレクトリ外へのexportが責務です。
|
|
37
|
+
実装などexport以外の記述は別ファイルに書き出してください。
|
|
38
|
+
|
|
39
|
+
許可されるパターン:
|
|
40
|
+
export { ... } from '...'
|
|
41
|
+
export type { ... } from '...'
|
|
42
|
+
export { default } from '...'
|
|
43
|
+
export { Foo as default } from '...'
|
|
44
|
+
|
|
45
|
+
詳細: https://github.com/kufu/tamatebako/tree/master/packages/eslint-plugin-smarthr/rules/require-barrel-import`,
|
|
46
|
+
})
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return {
|
|
50
|
+
// 禁止パターン
|
|
51
|
+
'ImportDeclaration, VariableDeclaration, FunctionDeclaration, ClassDeclaration, TSTypeAliasDeclaration, TSInterfaceDeclaration': reportPurityError,
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
module.exports = {
|
|
56
|
+
isBarrelFile,
|
|
57
|
+
createBarrelPurityVisitor,
|
|
58
|
+
}
|
|
@@ -2,6 +2,7 @@ const path = require('path')
|
|
|
2
2
|
const fs = require('fs')
|
|
3
3
|
const { replacePaths, rootPath } = require('../../libs/common')
|
|
4
4
|
const { getParentDir } = require('../../libs/util')
|
|
5
|
+
const { createBarrelPurityVisitor } = require('./barrel-purity-checker')
|
|
5
6
|
|
|
6
7
|
const SCHEMA = [
|
|
7
8
|
{
|
|
@@ -343,7 +344,14 @@ module.exports = {
|
|
|
343
344
|
}
|
|
344
345
|
}
|
|
345
346
|
|
|
346
|
-
|
|
347
|
+
// バレルファイル名のリストを作成
|
|
348
|
+
const additionalBarrelFileNames = option.additionalBarrelFileNames || []
|
|
349
|
+
const barrelFileNames = [...additionalBarrelFileNames, 'index']
|
|
350
|
+
|
|
351
|
+
// バレルファイルの純粋性チェックのビジターを作成
|
|
352
|
+
const purityVisitor = createBarrelPurityVisitor(context, barrelFileNames)
|
|
353
|
+
|
|
354
|
+
const importVisitor = {
|
|
347
355
|
ImportDeclaration: (node) => {
|
|
348
356
|
// allowedImportsチェック
|
|
349
357
|
const { shouldSkip, deniedModules } = checkAllowedImports(
|
|
@@ -572,6 +580,20 @@ export * from '${existingBarrelWithAlias}'
|
|
|
572
580
|
})
|
|
573
581
|
},
|
|
574
582
|
}
|
|
583
|
+
|
|
584
|
+
// purityVisitorとimportVisitorをマージ
|
|
585
|
+
// ImportDeclarationは両方にあるので、両方を実行する必要がある
|
|
586
|
+
return {
|
|
587
|
+
...purityVisitor,
|
|
588
|
+
ImportDeclaration: (node) => {
|
|
589
|
+
// purity checkerのImportDeclarationを先に実行
|
|
590
|
+
if (purityVisitor.ImportDeclaration) {
|
|
591
|
+
purityVisitor.ImportDeclaration(node)
|
|
592
|
+
}
|
|
593
|
+
// 既存のimportチェックを実行
|
|
594
|
+
importVisitor.ImportDeclaration(node)
|
|
595
|
+
},
|
|
596
|
+
}
|
|
575
597
|
},
|
|
576
598
|
}
|
|
577
599
|
module.exports.schema = SCHEMA
|
|
@@ -392,6 +392,134 @@ ruleTester.run('require-barrel-import', rule, {
|
|
|
392
392
|
parser: require('typescript-eslint').parser,
|
|
393
393
|
},
|
|
394
394
|
},
|
|
395
|
+
|
|
396
|
+
// ========================================
|
|
397
|
+
// バレルファイルの純粋性チェック - 許可されるパターン
|
|
398
|
+
// ========================================
|
|
399
|
+
|
|
400
|
+
// バレルファイルでexport { ... } from '...' は許可
|
|
401
|
+
{
|
|
402
|
+
code: `export { Button } from './Button'`,
|
|
403
|
+
filename: (() => {
|
|
404
|
+
createFixture('barrel-purity-valid-export-named', {
|
|
405
|
+
'components': {
|
|
406
|
+
'index.tsx': '',
|
|
407
|
+
'Button.tsx': '',
|
|
408
|
+
},
|
|
409
|
+
})
|
|
410
|
+
return `${fixturesRoot}/barrel-purity-valid-export-named/components/index.tsx`
|
|
411
|
+
})(),
|
|
412
|
+
},
|
|
413
|
+
|
|
414
|
+
// バレルファイルでexport * from '...' は許可
|
|
415
|
+
{
|
|
416
|
+
code: `export * from './Button'`,
|
|
417
|
+
filename: (() => {
|
|
418
|
+
createFixture('barrel-purity-valid-export-all', {
|
|
419
|
+
'components': {
|
|
420
|
+
'index.tsx': '',
|
|
421
|
+
'Button.tsx': '',
|
|
422
|
+
},
|
|
423
|
+
})
|
|
424
|
+
return `${fixturesRoot}/barrel-purity-valid-export-all/components/index.tsx`
|
|
425
|
+
})(),
|
|
426
|
+
},
|
|
427
|
+
|
|
428
|
+
// バレルファイルで複数のre-exportは許可
|
|
429
|
+
{
|
|
430
|
+
code: `
|
|
431
|
+
export { Button } from './Button'
|
|
432
|
+
export { Input } from './Input'
|
|
433
|
+
export * from './utils'
|
|
434
|
+
`,
|
|
435
|
+
filename: (() => {
|
|
436
|
+
createFixture('barrel-purity-valid-multiple', {
|
|
437
|
+
'components': {
|
|
438
|
+
'index.tsx': '',
|
|
439
|
+
'Button.tsx': '',
|
|
440
|
+
'Input.tsx': '',
|
|
441
|
+
'utils': {
|
|
442
|
+
'index.ts': '',
|
|
443
|
+
},
|
|
444
|
+
},
|
|
445
|
+
})
|
|
446
|
+
return `${fixturesRoot}/barrel-purity-valid-multiple/components/index.tsx`
|
|
447
|
+
})(),
|
|
448
|
+
},
|
|
449
|
+
|
|
450
|
+
// additionalBarrelFileNames(client.ts)でもre-exportは許可
|
|
451
|
+
{
|
|
452
|
+
code: `export { api } from './api'`,
|
|
453
|
+
filename: (() => {
|
|
454
|
+
createFixture('barrel-purity-valid-client', {
|
|
455
|
+
'services': {
|
|
456
|
+
'client.ts': '',
|
|
457
|
+
'api.ts': '',
|
|
458
|
+
},
|
|
459
|
+
})
|
|
460
|
+
return `${fixturesRoot}/barrel-purity-valid-client/services/client.ts`
|
|
461
|
+
})(),
|
|
462
|
+
options: [{ additionalBarrelFileNames: ['client', 'server'] }],
|
|
463
|
+
},
|
|
464
|
+
|
|
465
|
+
// TypeScript型のre-exportは許可
|
|
466
|
+
{
|
|
467
|
+
code: `export type { ButtonProps } from './Button'`,
|
|
468
|
+
filename: (() => {
|
|
469
|
+
createFixture('barrel-purity-valid-type-reexport', {
|
|
470
|
+
'components': {
|
|
471
|
+
'index.tsx': '',
|
|
472
|
+
'Button.tsx': '',
|
|
473
|
+
},
|
|
474
|
+
})
|
|
475
|
+
return `${fixturesRoot}/barrel-purity-valid-type-reexport/components/index.tsx`
|
|
476
|
+
})(),
|
|
477
|
+
languageOptions: {
|
|
478
|
+
parser: require('typescript-eslint').parser,
|
|
479
|
+
},
|
|
480
|
+
},
|
|
481
|
+
|
|
482
|
+
// default exportのre-exportは許可
|
|
483
|
+
{
|
|
484
|
+
code: `export { default } from './Component'`,
|
|
485
|
+
filename: (() => {
|
|
486
|
+
createFixture('barrel-purity-valid-default-reexport', {
|
|
487
|
+
'components': {
|
|
488
|
+
'index.ts': '',
|
|
489
|
+
'Component.tsx': '',
|
|
490
|
+
},
|
|
491
|
+
})
|
|
492
|
+
return `${fixturesRoot}/barrel-purity-valid-default-reexport/components/index.ts`
|
|
493
|
+
})(),
|
|
494
|
+
},
|
|
495
|
+
|
|
496
|
+
// default exportのre-export(as付き)は許可
|
|
497
|
+
{
|
|
498
|
+
code: `export { default as Button } from './Button'`,
|
|
499
|
+
filename: (() => {
|
|
500
|
+
createFixture('barrel-purity-valid-default-as-reexport', {
|
|
501
|
+
'components': {
|
|
502
|
+
'index.ts': '',
|
|
503
|
+
'Button.tsx': '',
|
|
504
|
+
},
|
|
505
|
+
})
|
|
506
|
+
return `${fixturesRoot}/barrel-purity-valid-default-as-reexport/components/index.ts`
|
|
507
|
+
})(),
|
|
508
|
+
},
|
|
509
|
+
|
|
510
|
+
// 【検証】named exportをdefaultとしてre-export
|
|
511
|
+
{
|
|
512
|
+
code: `export { Button as default } from './Button'`,
|
|
513
|
+
filename: (() => {
|
|
514
|
+
createFixture('barrel-purity-valid-named-as-default', {
|
|
515
|
+
'components': {
|
|
516
|
+
'index.ts': '',
|
|
517
|
+
'Button.tsx': '',
|
|
518
|
+
},
|
|
519
|
+
})
|
|
520
|
+
return `${fixturesRoot}/barrel-purity-valid-named-as-default/components/index.ts`
|
|
521
|
+
})(),
|
|
522
|
+
},
|
|
395
523
|
],
|
|
396
524
|
|
|
397
525
|
invalid: [
|
|
@@ -998,5 +1126,235 @@ ruleTester.run('require-barrel-import', rule, {
|
|
|
998
1126
|
},
|
|
999
1127
|
],
|
|
1000
1128
|
},
|
|
1129
|
+
|
|
1130
|
+
// ========================================
|
|
1131
|
+
// バレルファイルの純粋性チェック
|
|
1132
|
+
// ========================================
|
|
1133
|
+
|
|
1134
|
+
// 9. バレルファイル内でimport文を使用
|
|
1135
|
+
{
|
|
1136
|
+
code: `import { Button } from './Button'`,
|
|
1137
|
+
filename: (() => {
|
|
1138
|
+
createFixture('barrel-purity-import', {
|
|
1139
|
+
'components': {
|
|
1140
|
+
'index.tsx': '',
|
|
1141
|
+
'Button.tsx': '',
|
|
1142
|
+
},
|
|
1143
|
+
})
|
|
1144
|
+
return `${fixturesRoot}/barrel-purity-import/components/index.tsx`
|
|
1145
|
+
})(),
|
|
1146
|
+
errors: [
|
|
1147
|
+
{
|
|
1148
|
+
message: /バレルファイルは設置されたディレクトリ外へのexportが責務です/,
|
|
1149
|
+
},
|
|
1150
|
+
],
|
|
1151
|
+
},
|
|
1152
|
+
|
|
1153
|
+
// 10. バレルファイル内で変数定義
|
|
1154
|
+
{
|
|
1155
|
+
code: `const foo = 'bar'`,
|
|
1156
|
+
filename: (() => {
|
|
1157
|
+
createFixture('barrel-purity-const', {
|
|
1158
|
+
'components': {
|
|
1159
|
+
'index.tsx': '',
|
|
1160
|
+
},
|
|
1161
|
+
})
|
|
1162
|
+
return `${fixturesRoot}/barrel-purity-const/components/index.tsx`
|
|
1163
|
+
})(),
|
|
1164
|
+
errors: [
|
|
1165
|
+
{
|
|
1166
|
+
message: /バレルファイルは設置されたディレクトリ外へのexportが責務です/,
|
|
1167
|
+
},
|
|
1168
|
+
],
|
|
1169
|
+
},
|
|
1170
|
+
|
|
1171
|
+
// 11. バレルファイル内で関数定義
|
|
1172
|
+
{
|
|
1173
|
+
code: `function helper() { return 'test' }`,
|
|
1174
|
+
filename: (() => {
|
|
1175
|
+
createFixture('barrel-purity-function', {
|
|
1176
|
+
'utils': {
|
|
1177
|
+
'index.ts': '',
|
|
1178
|
+
},
|
|
1179
|
+
})
|
|
1180
|
+
return `${fixturesRoot}/barrel-purity-function/utils/index.ts`
|
|
1181
|
+
})(),
|
|
1182
|
+
errors: [
|
|
1183
|
+
{
|
|
1184
|
+
message: /バレルファイルは設置されたディレクトリ外へのexportが責務です/,
|
|
1185
|
+
},
|
|
1186
|
+
],
|
|
1187
|
+
},
|
|
1188
|
+
|
|
1189
|
+
// 12. バレルファイル内でexport function
|
|
1190
|
+
{
|
|
1191
|
+
code: `export function helper() { return 'test' }`,
|
|
1192
|
+
filename: (() => {
|
|
1193
|
+
createFixture('barrel-purity-export-function', {
|
|
1194
|
+
'utils': {
|
|
1195
|
+
'index.ts': '',
|
|
1196
|
+
},
|
|
1197
|
+
})
|
|
1198
|
+
return `${fixturesRoot}/barrel-purity-export-function/utils/index.ts`
|
|
1199
|
+
})(),
|
|
1200
|
+
errors: [
|
|
1201
|
+
{
|
|
1202
|
+
message: /バレルファイルは設置されたディレクトリ外へのexportが責務です/,
|
|
1203
|
+
},
|
|
1204
|
+
],
|
|
1205
|
+
},
|
|
1206
|
+
|
|
1207
|
+
// 13. バレルファイル内でクラス定義
|
|
1208
|
+
{
|
|
1209
|
+
code: `class MyClass {}`,
|
|
1210
|
+
filename: (() => {
|
|
1211
|
+
createFixture('barrel-purity-class', {
|
|
1212
|
+
'models': {
|
|
1213
|
+
'index.ts': '',
|
|
1214
|
+
},
|
|
1215
|
+
})
|
|
1216
|
+
return `${fixturesRoot}/barrel-purity-class/models/index.ts`
|
|
1217
|
+
})(),
|
|
1218
|
+
errors: [
|
|
1219
|
+
{
|
|
1220
|
+
message: /バレルファイルは設置されたディレクトリ外へのexportが責務です/,
|
|
1221
|
+
},
|
|
1222
|
+
],
|
|
1223
|
+
},
|
|
1224
|
+
|
|
1225
|
+
// 14. バレルファイル内でexport class
|
|
1226
|
+
{
|
|
1227
|
+
code: `export class MyClass {}`,
|
|
1228
|
+
filename: (() => {
|
|
1229
|
+
createFixture('barrel-purity-export-class', {
|
|
1230
|
+
'models': {
|
|
1231
|
+
'index.ts': '',
|
|
1232
|
+
},
|
|
1233
|
+
})
|
|
1234
|
+
return `${fixturesRoot}/barrel-purity-export-class/models/index.ts`
|
|
1235
|
+
})(),
|
|
1236
|
+
errors: [
|
|
1237
|
+
{
|
|
1238
|
+
message: /バレルファイルは設置されたディレクトリ外へのexportが責務です/,
|
|
1239
|
+
},
|
|
1240
|
+
],
|
|
1241
|
+
},
|
|
1242
|
+
|
|
1243
|
+
// 15. バレルファイル内で変数定義とexport { foo }
|
|
1244
|
+
// export { foo } は定義(const foo)が禁止されているため、実質的に発生しない
|
|
1245
|
+
{
|
|
1246
|
+
code: `const foo = 'bar'`,
|
|
1247
|
+
filename: (() => {
|
|
1248
|
+
createFixture('barrel-purity-export-local', {
|
|
1249
|
+
'utils': {
|
|
1250
|
+
'index.ts': '',
|
|
1251
|
+
},
|
|
1252
|
+
})
|
|
1253
|
+
return `${fixturesRoot}/barrel-purity-export-local/utils/index.ts`
|
|
1254
|
+
})(),
|
|
1255
|
+
errors: [
|
|
1256
|
+
{
|
|
1257
|
+
message: /バレルファイルは設置されたディレクトリ外へのexportが責務です/,
|
|
1258
|
+
},
|
|
1259
|
+
],
|
|
1260
|
+
},
|
|
1261
|
+
|
|
1262
|
+
// 17. additionalBarrelFileNames(client.ts)でもpurityチェック
|
|
1263
|
+
{
|
|
1264
|
+
code: `import { api } from './api'`,
|
|
1265
|
+
filename: (() => {
|
|
1266
|
+
createFixture('barrel-purity-client', {
|
|
1267
|
+
'services': {
|
|
1268
|
+
'client.ts': '',
|
|
1269
|
+
'api.ts': '',
|
|
1270
|
+
},
|
|
1271
|
+
})
|
|
1272
|
+
return `${fixturesRoot}/barrel-purity-client/services/client.ts`
|
|
1273
|
+
})(),
|
|
1274
|
+
options: [{ additionalBarrelFileNames: ['client', 'server'] }],
|
|
1275
|
+
errors: [
|
|
1276
|
+
{
|
|
1277
|
+
message: /バレルファイルは設置されたディレクトリ外へのexportが責務です/,
|
|
1278
|
+
},
|
|
1279
|
+
],
|
|
1280
|
+
},
|
|
1281
|
+
|
|
1282
|
+
// 18. バレルファイル内で型エイリアス定義
|
|
1283
|
+
{
|
|
1284
|
+
code: `export type Size = 'small' | 'medium' | 'large'`,
|
|
1285
|
+
filename: (() => {
|
|
1286
|
+
createFixture('barrel-purity-type-alias', {
|
|
1287
|
+
'components': {
|
|
1288
|
+
'index.ts': '',
|
|
1289
|
+
},
|
|
1290
|
+
})
|
|
1291
|
+
return `${fixturesRoot}/barrel-purity-type-alias/components/index.ts`
|
|
1292
|
+
})(),
|
|
1293
|
+
languageOptions: {
|
|
1294
|
+
parser: require('typescript-eslint').parser,
|
|
1295
|
+
},
|
|
1296
|
+
errors: [
|
|
1297
|
+
{
|
|
1298
|
+
message: /バレルファイルは設置されたディレクトリ外へのexportが責務です/,
|
|
1299
|
+
},
|
|
1300
|
+
],
|
|
1301
|
+
},
|
|
1302
|
+
|
|
1303
|
+
// 19. バレルファイル内でインターフェース定義
|
|
1304
|
+
{
|
|
1305
|
+
code: `export interface ComponentAPI { render: () => void }`,
|
|
1306
|
+
filename: (() => {
|
|
1307
|
+
createFixture('barrel-purity-interface', {
|
|
1308
|
+
'components': {
|
|
1309
|
+
'index.ts': '',
|
|
1310
|
+
},
|
|
1311
|
+
})
|
|
1312
|
+
return `${fixturesRoot}/barrel-purity-interface/components/index.ts`
|
|
1313
|
+
})(),
|
|
1314
|
+
languageOptions: {
|
|
1315
|
+
parser: require('typescript-eslint').parser,
|
|
1316
|
+
},
|
|
1317
|
+
errors: [
|
|
1318
|
+
{
|
|
1319
|
+
message: /バレルファイルは設置されたディレクトリ外へのexportが責務です/,
|
|
1320
|
+
},
|
|
1321
|
+
],
|
|
1322
|
+
},
|
|
1323
|
+
|
|
1324
|
+
// 20. 【検証用】バレルファイル内でexport default function(禁止)
|
|
1325
|
+
{
|
|
1326
|
+
code: `export default function Page() { return null }`,
|
|
1327
|
+
filename: (() => {
|
|
1328
|
+
createFixture('barrel-purity-export-default-function', {
|
|
1329
|
+
'components': {
|
|
1330
|
+
'index.tsx': '',
|
|
1331
|
+
},
|
|
1332
|
+
})
|
|
1333
|
+
return `${fixturesRoot}/barrel-purity-export-default-function/components/index.tsx`
|
|
1334
|
+
})(),
|
|
1335
|
+
errors: [
|
|
1336
|
+
{
|
|
1337
|
+
message: /バレルファイルは設置されたディレクトリ外へのexportが責務です/,
|
|
1338
|
+
},
|
|
1339
|
+
],
|
|
1340
|
+
},
|
|
1341
|
+
|
|
1342
|
+
// 21. 【検証用】バレルファイル内でexport default class(禁止)
|
|
1343
|
+
{
|
|
1344
|
+
code: `export default class MyComponent {}`,
|
|
1345
|
+
filename: (() => {
|
|
1346
|
+
createFixture('barrel-purity-export-default-class', {
|
|
1347
|
+
'components': {
|
|
1348
|
+
'index.tsx': '',
|
|
1349
|
+
},
|
|
1350
|
+
})
|
|
1351
|
+
return `${fixturesRoot}/barrel-purity-export-default-class/components/index.tsx`
|
|
1352
|
+
})(),
|
|
1353
|
+
errors: [
|
|
1354
|
+
{
|
|
1355
|
+
message: /バレルファイルは設置されたディレクトリ外へのexportが責務です/,
|
|
1356
|
+
},
|
|
1357
|
+
],
|
|
1358
|
+
},
|
|
1001
1359
|
],
|
|
1002
1360
|
})
|
|
@@ -1,127 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"permissions": {
|
|
3
|
-
"allow": [
|
|
4
|
-
"Bash(npm test:*)",
|
|
5
|
-
"Bash(git checkout:*)",
|
|
6
|
-
"Bash(git pull:*)",
|
|
7
|
-
"Bash(git add:*)",
|
|
8
|
-
"Bash(git commit:*)",
|
|
9
|
-
"Bash(git push:*)",
|
|
10
|
-
"Bash(gh pr:*)",
|
|
11
|
-
"Bash(brew upgrade:*)",
|
|
12
|
-
"Bash(git fetch:*)",
|
|
13
|
-
"Bash(git merge:*)",
|
|
14
|
-
"Bash(git restore:*)",
|
|
15
|
-
"Bash(git reset:*)",
|
|
16
|
-
"Bash(grep -l \"node\\) =>\" rules/*/index.js)",
|
|
17
|
-
"Bash(git branch:*)",
|
|
18
|
-
"Bash(git revert:*)",
|
|
19
|
-
"Bash(column -t -s '|')",
|
|
20
|
-
"Bash(gh api:*)",
|
|
21
|
-
"Bash(grep -r \"=\\\\{[''''\"\"\\\\`][a-zA-Z0-9]*[''''\"\"\\\\`]\\\\}\" test/*.js)",
|
|
22
|
-
"Bash(grep -E \"=\\\\{[''''\"\"\\\\`]\" test/*.js)",
|
|
23
|
-
"Bash(grep \"name={\\\\`ABC\\\\`}\")",
|
|
24
|
-
"Bash(grep -nE \"=\\\\{\\\\`[^$\\\\`]*\\\\`\\\\}\" test/*.js)",
|
|
25
|
-
"Read(//Users/atsushi.mizoue/works/tamatebako/**)",
|
|
26
|
-
"Bash(pnpm install:*)",
|
|
27
|
-
"Bash(pnpm test:*)",
|
|
28
|
-
"Bash(grep -v '^master$')",
|
|
29
|
-
"Bash(grep -E \"FieldSet|BaseColumn|Message$|Fieldsets|FormControls|RadioButtons|RadioButtonPanels|Checkboxes\" test/component-name.js)",
|
|
30
|
-
"Bash(git stash:*)",
|
|
31
|
-
"Bash(grep -n \"new RegExp\" rules/*/index.js)",
|
|
32
|
-
"Bash(grep -nE \"\\\\.replace\\\\\\(\\\\/|\\\\.test\\\\\\(\\\\/|\\\\.match\\\\\\(\\\\/|\\\\.exec\\\\\\(\\\\/|\\\\.search\\\\\\(\\\\/\" rules/*/index.js)",
|
|
33
|
-
"Bash(grep -nE \"const .* = /\" rules/*/index.js)",
|
|
34
|
-
"Bash(grep -n \"Object.keys\\(\" rules/*/index.js)",
|
|
35
|
-
"Bash(grep -n \"const.*=.*Object\\\\.keys\\(\" rules/*/index.js)",
|
|
36
|
-
"Bash(grep:*)",
|
|
37
|
-
"Bash(grep -n \"\\\\.forEach\\(\" rules/*/index.js)",
|
|
38
|
-
"Bash(sort -k1,1 -k3,3)",
|
|
39
|
-
"Bash(for branch:*)",
|
|
40
|
-
"Bash(do)",
|
|
41
|
-
"Bash(echo \"=== $branch ===\")",
|
|
42
|
-
"Bash(git log:*)",
|
|
43
|
-
"Bash(done)",
|
|
44
|
-
"WebSearch",
|
|
45
|
-
"Bash(git mv:*)",
|
|
46
|
-
"Bash(node:*)",
|
|
47
|
-
"Bash(do echo:*)",
|
|
48
|
-
"Bash(echo \"Checking files...\" git ls-tree -r --name-only $branch packages/eslint-plugin-smarthr/rules/)",
|
|
49
|
-
"Bash(git ls-tree:*)",
|
|
50
|
-
"Bash(git config:*)",
|
|
51
|
-
"Bash(npm run:*)",
|
|
52
|
-
"Bash(ls rules/*/README.md)",
|
|
53
|
-
"Bash(find rules:*)",
|
|
54
|
-
"Bash(cp:*)",
|
|
55
|
-
"Bash(cd:*)",
|
|
56
|
-
"Bash(/Users/atsushi.mizoue/works/hanica/client/eslint/rules/best-practice-for-response-message.cjs:*)",
|
|
57
|
-
"Bash(/Users/atsushi.mizoue/works/hanica/client/eslint/rules/a11y-prohibit-overflow-hidden.cjs:*)",
|
|
58
|
-
"Bash(/Users/atsushi.mizoue/works/hanica/client/eslint/rules/a11y-scroller-has-tabindex.cjs:*)",
|
|
59
|
-
"Bash(__NEW_LINE_aaf112b90809b36f__ cat:*)",
|
|
60
|
-
"Bash(/Users/atsushi.mizoue/works/hanica/client/eslint/rules/best-practice-for-text-component.cjs:*)",
|
|
61
|
-
"Bash(/Users/atsushi.mizoue/works/hanica/client/eslint/rules/design-system-guideline-prohibit-dialog-button-icon.cjs:*)",
|
|
62
|
-
"Bash(__NEW_LINE_220f471abdeba11e__ cat:*)",
|
|
63
|
-
"Bash(for dir:*)",
|
|
64
|
-
"Bash(do if:*)",
|
|
65
|
-
"Read(//Users/atsushi.mizoue/works/tamatebako/packages/eslint-plugin-smarthr/$dir/**)",
|
|
66
|
-
"Bash(then echo:*)",
|
|
67
|
-
"Bash(fi)",
|
|
68
|
-
"Bash(pnpm eslint:*)",
|
|
69
|
-
"Bash(git cherry-pick:*)",
|
|
70
|
-
"Bash(git rebase:*)",
|
|
71
|
-
"Bash(GIT_SEQUENCE_EDITOR=\"sed -i '/fix: best-practice-for-text-component/d'\" git rebase -i HEAD~34)",
|
|
72
|
-
"Bash(gh search:*)",
|
|
73
|
-
"Bash(gh repo:*)",
|
|
74
|
-
"Bash(jq)",
|
|
75
|
-
"Bash(find . -name \"package.json\" -not -path \"*/node_modules/*\" -exec grep -l \"smarthr-ui\" {})",
|
|
76
|
-
"Bash(mkdir -p /Users/atsushi.mizoue/works/workflow/michi/frontend/eslint/rules/autofixer-smarthr-ui-migration)",
|
|
77
|
-
"Bash(cp -r /Users/atsushi.mizoue/works/tamatebako/packages/eslint-plugin-smarthr/rules/autofixer-smarthr-ui-migration/* /Users/atsushi.mizoue/works/workflow/michi/frontend/eslint/rules/autofixer-smarthr-ui-migration/)",
|
|
78
|
-
"Bash(pnpm link:*)",
|
|
79
|
-
"Bash(pnpm add:*)",
|
|
80
|
-
"Bash(pnpm run:*)",
|
|
81
|
-
"Bash(pnpm view:*)",
|
|
82
|
-
"Bash(pnpm exec:*)",
|
|
83
|
-
"Bash(pnpm list:*)",
|
|
84
|
-
"Bash(find /Users/atsushi.mizoue/works/workflow/michi/frontend/node_modules/.pnpm -name eslint-plugin-smarthr* -type d)",
|
|
85
|
-
"Bash(ls -la /Users/atsushi.mizoue/works/workflow/michi/frontend/node_modules/.pnpm/eslint-config-smarthr@13.10.0_*/node_modules/)",
|
|
86
|
-
"Read(//Users/atsushi.mizoue/works/workflow/**)",
|
|
87
|
-
"Bash(rm -rf pnpm-lock.yaml node_modules/.pnpm)",
|
|
88
|
-
"Bash(ls:*)",
|
|
89
|
-
"Bash(xargs curl:*)",
|
|
90
|
-
"Bash(xargs -I {} gh api repos/kufu/smarthr-ui/contents/packages/smarthr-ui/src/components/Dialog/ActionDialog/ActionDialogContentInner.tsx?ref={} --jq '.content')",
|
|
91
|
-
"Bash(npm view:*)",
|
|
92
|
-
"Bash(gh run:*)",
|
|
93
|
-
"Bash(xargs -I {} gh api repos/kufu/tamatebako/contents/packages/eslint-plugin-smarthr/CHANGELOG.md?ref={} --jq '.content')",
|
|
94
|
-
"Bash(/tmp/new-return-body.js:*)",
|
|
95
|
-
"Bash(git rm:*)",
|
|
96
|
-
"Bash(gh release:*)",
|
|
97
|
-
"Bash(ls -la /Users/atsushi.mizoue/works/workflow/kago/frontend/src/app/\\\\\\(private\\\\\\)/settings/user_roles/_components/UserRolesPage/UserRoleTable/)",
|
|
98
|
-
"Bash(ls -la \"/Users/atsushi.mizoue/works/workflow/kago/frontend/src/app/\\(private\\)/settings/user_roles/_components/UserRolesPage/UserRoleTable/DeleteUserRoleDialog/\")",
|
|
99
|
-
"Bash(tee /tmp/eslint-test-output.txt)",
|
|
100
|
-
"Bash(find /Users/atsushi.mizoue/works/workflow/kago/frontend/src -type d -name \"*\\(*\")",
|
|
101
|
-
"Bash(test -d \"/Users/atsushi.mizoue/works/workflow/kago/frontend/src/app/\\(private\\)/settings/user_roles/_components/AddUserRoleDialog/hooks/useUsers\")",
|
|
102
|
-
"Bash(pkill -f eslint)",
|
|
103
|
-
"Bash(npx eslint:*)",
|
|
104
|
-
"Bash(/tmp/pr-body.md:*)",
|
|
105
|
-
"Bash(pkill -9 -f eslint)",
|
|
106
|
-
"Bash(rm -rf .eslintcache node_modules/.cache)",
|
|
107
|
-
"Bash(pnpm remove:*)",
|
|
108
|
-
"Bash(find test:*)",
|
|
109
|
-
"Bash(git clean:*)",
|
|
110
|
-
"Bash(open \"https://github.com/kufu/tamatebako/pull/1244\")",
|
|
111
|
-
"Bash(test-multiple-barrels.tsx:*)",
|
|
112
|
-
"Bash(src/test-multiple-barrels.tsx:*)",
|
|
113
|
-
"Bash(src/components/test-multiple-barrels.tsx:*)",
|
|
114
|
-
"Bash(src/components/pages/routes/route/edit/_components/test-multiple-barrels.tsx:*)",
|
|
115
|
-
"Bash(src/app/test-both-barrels.tsx:*)",
|
|
116
|
-
"Bash(pnpm release:*)",
|
|
117
|
-
"Bash(npm whoami:*)",
|
|
118
|
-
"Bash(for pr:*)",
|
|
119
|
-
"Bash(npx lerna:*)",
|
|
120
|
-
"Bash(npm login:*)",
|
|
121
|
-
"Bash(curl -s https://raw.githubusercontent.com/kufu/smarthr-ui/main/CHANGELOG.md)",
|
|
122
|
-
"Bash(npm pack:*)",
|
|
123
|
-
"Bash(npx prettier:*)",
|
|
124
|
-
"Bash(pnpm prerelease:*)"
|
|
125
|
-
]
|
|
126
|
-
}
|
|
127
|
-
}
|