eslint-plugin-smarthr 6.11.0 → 6.12.1
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/.claude/settings.local.json +124 -0
- package/CHANGELOG.md +19 -0
- package/package.json +2 -2
- package/rules/autofixer-smarthr-ui-migration/versions/v91-to-v92/index.js +15 -14
- package/rules/autofixer-smarthr-ui-migration/versions/v91-to-v92/test.js +15 -2
- package/rules/format-import-path/index.js +5 -1
- package/rules/require-barrel-import/README.md +142 -7
- package/rules/require-barrel-import/index.js +279 -36
- package/test/require-barrel-import.js +607 -0
|
@@ -0,0 +1,124 @@
|
|
|
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
|
+
]
|
|
123
|
+
}
|
|
124
|
+
}
|
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,25 @@
|
|
|
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.12.1](https://github.com/kufu/tamatebako/compare/eslint-plugin-smarthr-v6.12.0...eslint-plugin-smarthr-v6.12.1) (2026-04-19)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### Bug Fixes
|
|
9
|
+
|
|
10
|
+
* **v91-to-v92:** button/anchorButton系変種コンポーネントのsize属性変換に対応 ([#1251](https://github.com/kufu/tamatebako/issues/1251)) ([14335be](https://github.com/kufu/tamatebako/commit/14335bef82fa38ebe04b0b16fda5e5cd06165cae))
|
|
11
|
+
|
|
12
|
+
## [6.12.0](https://github.com/kufu/tamatebako/compare/eslint-plugin-smarthr-v6.11.0...eslint-plugin-smarthr-v6.12.0) (2026-04-15)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
### Features
|
|
16
|
+
|
|
17
|
+
* **require-barrel-import:** additionalBarrelFileNamesオプション追加と同階層・子階層からのバレルimport禁止 ([#1244](https://github.com/kufu/tamatebako/issues/1244)) ([b38a143](https://github.com/kufu/tamatebako/commit/b38a1432a92bd3ee4e52f3a450177e59f65512f0))
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
### Bug Fixes
|
|
21
|
+
|
|
22
|
+
* **format-import-path:** dirCount関数でmatch結果がnullの場合のエラーを修正 ([#1246](https://github.com/kufu/tamatebako/issues/1246)) ([fc50fba](https://github.com/kufu/tamatebako/commit/fc50fbadc3da3b046a73bbab664c281fc7be847f))
|
|
23
|
+
|
|
5
24
|
## [6.11.0](https://github.com/kufu/tamatebako/compare/eslint-plugin-smarthr-v6.10.4...eslint-plugin-smarthr-v6.11.0) (2026-04-14)
|
|
6
25
|
|
|
7
26
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-plugin-smarthr",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.12.1",
|
|
4
4
|
"author": "SmartHR",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"description": "A sharable ESLint plugin for SmartHR",
|
|
@@ -34,5 +34,5 @@
|
|
|
34
34
|
"eslintplugin",
|
|
35
35
|
"smarthr"
|
|
36
36
|
],
|
|
37
|
-
"gitHead": "
|
|
37
|
+
"gitHead": "3b8ac2fc343826a86b14d05ffc9400c417ce3814"
|
|
38
38
|
}
|
|
@@ -39,18 +39,18 @@ const SIZE_VALUE_MAP = {
|
|
|
39
39
|
m: 'M',
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
//
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
42
|
+
// サイズ指定を持つコンポーネント(正規表現パターン)
|
|
43
|
+
const SIZE_COMPONENT_PATTERNS = [
|
|
44
|
+
/Button$/, // XxxxButton (例: Button, PrimaryButton, DangerButton)
|
|
45
|
+
/AnchorButton$/, // XxxxAnchorButton (例: AnchorButton, PrimaryAnchorButton, DangerAnchorButton)
|
|
46
|
+
/^Select$/,
|
|
47
|
+
/^SegmentedControl$/,
|
|
48
|
+
/^SideNav$/,
|
|
49
|
+
/^SideNavItemButton$/,
|
|
50
|
+
/^SideNavItemAnchor$/,
|
|
51
|
+
/^InputFile$/,
|
|
52
|
+
/^Loader$/,
|
|
53
|
+
/^LoaderSpinner$/,
|
|
54
54
|
]
|
|
55
55
|
|
|
56
56
|
// 3. decorators属性を持つコンポーネント
|
|
@@ -285,8 +285,9 @@ module.exports = {
|
|
|
285
285
|
'JSXAttribute[name.name="size"][value.type="Literal"]'(node) {
|
|
286
286
|
const componentName = node.parent.name.name
|
|
287
287
|
|
|
288
|
-
//
|
|
289
|
-
|
|
288
|
+
// 対象コンポーネントかチェック(正規表現パターンマッチング)
|
|
289
|
+
const isTargetComponent = SIZE_COMPONENT_PATTERNS.some(pattern => pattern.test(componentName))
|
|
290
|
+
if (!isTargetComponent) return
|
|
290
291
|
|
|
291
292
|
const sizeValue = node.value.value
|
|
292
293
|
const newValue = SIZE_VALUE_MAP[sizeValue]
|
|
@@ -59,8 +59,7 @@ module.exports = {
|
|
|
59
59
|
{ code: `<Button />`, options: v91ToV92Options },
|
|
60
60
|
{ code: `<Button size={dynamicSize} />`, options: v91ToV92Options },
|
|
61
61
|
|
|
62
|
-
//
|
|
63
|
-
{ code: `<CustomButton size="default" />`, options: v91ToV92Options },
|
|
62
|
+
// 対象外のコンポーネント(Buttonサフィックスを持たないもの)
|
|
64
63
|
{ code: `<Text size="s" />`, options: v91ToV92Options },
|
|
65
64
|
|
|
66
65
|
// smarthrUiAliasオプション: aliasファイル外では置換しない
|
|
@@ -176,6 +175,20 @@ const handleAction: ComponentPropsWithoutRef<typeof FormDialog>['onClickClose']
|
|
|
176
175
|
createSizeConversionTest('Button', 's', 'S'),
|
|
177
176
|
createSizeConversionTest('AnchorButton', 'default', 'M'),
|
|
178
177
|
|
|
178
|
+
// Button variants
|
|
179
|
+
createSizeConversionTest('PrimaryButton', 's', 'S'),
|
|
180
|
+
createSizeConversionTest('PrimaryButton', 'default', 'M'),
|
|
181
|
+
createSizeConversionTest('DangerButton', 's', 'S'),
|
|
182
|
+
createSizeConversionTest('SkeletonButton', 's', 'S'),
|
|
183
|
+
createSizeConversionTest('TextButton', 's', 'S'),
|
|
184
|
+
|
|
185
|
+
// AnchorButton variants
|
|
186
|
+
createSizeConversionTest('PrimaryAnchorButton', 's', 'S'),
|
|
187
|
+
createSizeConversionTest('PrimaryAnchorButton', 'default', 'M'),
|
|
188
|
+
createSizeConversionTest('DangerAnchorButton', 's', 'S'),
|
|
189
|
+
createSizeConversionTest('SkeletonAnchorButton', 's', 'S'),
|
|
190
|
+
createSizeConversionTest('TextAnchorButton', 's', 'S'),
|
|
191
|
+
|
|
179
192
|
// Select
|
|
180
193
|
createSizeConversionTest('Select', 's', 'S'),
|
|
181
194
|
createSizeConversionTest('Select', 'm', 'M'),
|
|
@@ -28,7 +28,11 @@ const DIR_SEPARATE_REGEX = /\//g
|
|
|
28
28
|
const MULTIPLE_DIR_SEPARATE_REGEX =/(\/)+/g
|
|
29
29
|
const TRAILING_SLASH_REGEX = /^(.+?)\/$/
|
|
30
30
|
|
|
31
|
-
const dirCount = (dir) =>
|
|
31
|
+
const dirCount = (dir) => {
|
|
32
|
+
if (!dir) return 0
|
|
33
|
+
const matches = dir.match(DIR_SEPARATE_REGEX)
|
|
34
|
+
return matches ? matches.length : 0
|
|
35
|
+
}
|
|
32
36
|
|
|
33
37
|
const convertType = (calcContext, calcDomainNode) => {
|
|
34
38
|
const { option: { format: { all, outside, globalModule, module, domain, lower } } } = calcContext
|
|
@@ -24,6 +24,49 @@ barrelを経由することで、内部のファイル構成を変更しても
|
|
|
24
24
|
|
|
25
25
|
例えば、`Page/parts/Menu/Item` を `Page/parts/Menu` から importすることで、import文がより簡潔で読みやすくなります。
|
|
26
26
|
|
|
27
|
+
## 同階層・子階層からのバレルimportの禁止
|
|
28
|
+
|
|
29
|
+
バレルファイル(index.ts、client.ts等)と同じディレクトリまたは子ディレクトリ内からバレルファイルをimportすることを禁止します。
|
|
30
|
+
|
|
31
|
+
### なぜ禁止する必要があるのか
|
|
32
|
+
|
|
33
|
+
バレルファイルは**ディレクトリ外部**へのエクスポート専用として設計されています。同じディレクトリ内や子ディレクトリからバレルファイルをimportすると、以下の問題が発生します:
|
|
34
|
+
|
|
35
|
+
1. **循環参照のリスク**: バレルファイルが内部のファイルをexportし、その内部ファイルがバレルファイルをimportする循環が発生しやすい
|
|
36
|
+
2. **カプセル化の崩壊**: バレルファイルは外部向けAPIであり、内部からimportすると内部実装の境界が曖昧になる
|
|
37
|
+
3. **不要な依存**: 直接相対パスでimportできるものをバレル経由でimportすることは冗長
|
|
38
|
+
|
|
39
|
+
### ❌ 検出されるエラーケース
|
|
40
|
+
|
|
41
|
+
```typescript
|
|
42
|
+
// src/components/Button/Button.tsx から同じディレクトリのバレルをimport
|
|
43
|
+
import { ButtonProps } from '.' // NG
|
|
44
|
+
import { ButtonProps } from './index' // NG
|
|
45
|
+
import { ButtonProps } from '@/components/Button' // NG
|
|
46
|
+
|
|
47
|
+
// src/components/Button/_utils/helper.ts から親のバレルをimport
|
|
48
|
+
import { Button } from '..' // NG
|
|
49
|
+
import { Button } from '../index' // NG
|
|
50
|
+
import { Button } from '@/components/Button' // NG
|
|
51
|
+
|
|
52
|
+
// client.ts を使用している場合
|
|
53
|
+
import { ButtonPresentation } from './client' // NG
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### ✅ 正しいimport方法
|
|
57
|
+
|
|
58
|
+
```typescript
|
|
59
|
+
// 同じディレクトリ内では直接相対パスを使用
|
|
60
|
+
import { ButtonProps } from './types' // OK
|
|
61
|
+
|
|
62
|
+
// 親ディレクトリのファイルも直接相対パスを使用
|
|
63
|
+
import { buttonUtils } from '../utils' // OK
|
|
64
|
+
|
|
65
|
+
// バレルファイルは外部ディレクトリからのみimport
|
|
66
|
+
// src/pages/HomePage.tsx から
|
|
67
|
+
import { Button } from '@/components/Button' // OK
|
|
68
|
+
```
|
|
69
|
+
|
|
27
70
|
## config
|
|
28
71
|
|
|
29
72
|
### 必須設定
|
|
@@ -43,6 +86,95 @@ tsconfig.json の compilerOptions.pathsに `@/*` もしくは `~/*` としてroo
|
|
|
43
86
|
|
|
44
87
|
特定のファイルから特定のimportを許可する設定を記述できます。
|
|
45
88
|
|
|
89
|
+
### additionalBarrelFileNames
|
|
90
|
+
|
|
91
|
+
`index` 以外にbarrelファイルとして扱うファイル名を配列で指定します(拡張子なし)。
|
|
92
|
+
|
|
93
|
+
Next.jsなどで使用される `client.ts` をbarrelファイルとして扱いたい場合に使用します。
|
|
94
|
+
|
|
95
|
+
- デフォルト: `[]`(`index.*` のみがbarrelファイル)
|
|
96
|
+
- 例: `['client']` を指定すると、`client.ts`, `client.tsx` などもbarrelファイルとして扱われます
|
|
97
|
+
- 複数指定も可能: `['client', 'server']` を指定すると、`server.ts`, `server.tsx` なども追加されます
|
|
98
|
+
|
|
99
|
+
#### 優先順位とチェックルール
|
|
100
|
+
|
|
101
|
+
**1. 同じディレクトリ内に複数のbarrelがある場合**
|
|
102
|
+
- `client.ts` と `index.ts` が両方ある場合、どちらからのimportも許容されます
|
|
103
|
+
- 例: `import { Foo } from './api'` も `import { Foo } from './api/client'` もOK
|
|
104
|
+
|
|
105
|
+
**2. 同じファイル名の場合は親を優先**
|
|
106
|
+
|
|
107
|
+
探索により同じファイル名のbarrelが複数見つかった場合(例: `client.ts`同士、`index.ts`同士)、より親のbarrelを推奨します。
|
|
108
|
+
|
|
109
|
+
```typescript
|
|
110
|
+
// 例: 同じファイル名の場合(index同士)
|
|
111
|
+
route/
|
|
112
|
+
index.ts ← より親を推奨
|
|
113
|
+
edit/
|
|
114
|
+
index.ts
|
|
115
|
+
|
|
116
|
+
// import { Foo } from './route/edit/Foo'
|
|
117
|
+
// → route/index.ts を推奨(より親のbarrel)
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
**index.ts経由のre-export対応:**
|
|
121
|
+
|
|
122
|
+
子で`index.ts`を見つけた場合でも、親方向に`client.ts`があれば、そちらを優先します。
|
|
123
|
+
|
|
124
|
+
```typescript
|
|
125
|
+
// 子が index.ts、親が client.ts のパターン
|
|
126
|
+
route/
|
|
127
|
+
client.ts ← これを推奨
|
|
128
|
+
edit/
|
|
129
|
+
index.ts
|
|
130
|
+
|
|
131
|
+
// import { Foo } from './route/edit/Foo'
|
|
132
|
+
// → route/client.ts を推奨(親のclient.tsが見つかった)
|
|
133
|
+
|
|
134
|
+
// この場合、route/client.ts で edit/index.ts をre-exportする想定:
|
|
135
|
+
// route/client.ts
|
|
136
|
+
export * from './edit'
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
**3. エラーメッセージの表示**
|
|
140
|
+
|
|
141
|
+
`additionalBarrelFileNames`が設定されている場合、エラーメッセージには存在しないbarrelファイルも含めて全ての選択肢が表示されます。
|
|
142
|
+
|
|
143
|
+
```typescript
|
|
144
|
+
// 例: additionalBarrelFileNames: ['client'] 設定時、index.tsのみ存在
|
|
145
|
+
検出されたバレル: @/components/api/index.ts
|
|
146
|
+
現在のimport: import { fetchUser } from '@/components/api/user'
|
|
147
|
+
推奨されるimport(以下のいずれか):
|
|
148
|
+
- import { fetchUser } from '@/components/api' // index.ts
|
|
149
|
+
- import { fetchUser } from '@/components/api/client' // client.ts (作成が必要)
|
|
150
|
+
|
|
151
|
+
※ 存在しないバレルファイルは必要に応じて作成してください。
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
- `index.ts`が優先的に表示されます(常に最初)
|
|
155
|
+
- 存在しないファイルには `(作成が必要)` マークが表示されます
|
|
156
|
+
- 存在しないファイルがある場合、注意メッセージが追加されます
|
|
157
|
+
- 「検出されたバレル」には実際に存在するファイルのみが表示されます
|
|
158
|
+
|
|
159
|
+
**4. 階層の一貫性チェック**
|
|
160
|
+
|
|
161
|
+
子ディレクトリで`client.ts`を使用している場合、親ディレクトリにも同名のbarrelを作成することを促します。これにより、プロジェクト全体でbarrel構造の一貫性を保ちます。
|
|
162
|
+
|
|
163
|
+
```typescript
|
|
164
|
+
// 例: client.tsパターンの一貫性チェック
|
|
165
|
+
route/
|
|
166
|
+
index.ts ← client.tsがない
|
|
167
|
+
edit/
|
|
168
|
+
client.ts ← client.tsを使用
|
|
169
|
+
|
|
170
|
+
// import { Foo } from './route/edit/client'
|
|
171
|
+
// → エラー: route/client.ts を作成して、edit/client のexportをまとめてください
|
|
172
|
+
|
|
173
|
+
// この場合、以下のようにroute/client.tsを作成する必要があります:
|
|
174
|
+
// route/client.ts
|
|
175
|
+
export * from './edit/client'
|
|
176
|
+
```
|
|
177
|
+
|
|
46
178
|
## rules
|
|
47
179
|
|
|
48
180
|
```js
|
|
@@ -50,13 +182,16 @@ tsconfig.json の compilerOptions.pathsに `@/*` もしくは `~/*` としてroo
|
|
|
50
182
|
rules: {
|
|
51
183
|
'smarthr/require-barrel-import': [
|
|
52
184
|
'error',
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
185
|
+
{
|
|
186
|
+
// ignores: ['\\/test\\/'], // 除外したいファイルの正規表現
|
|
187
|
+
// allowedImports: {
|
|
188
|
+
// '/any/path/': { // 正規表現でチェックするファイルを指定
|
|
189
|
+
// // import制御するファイル (相対パスを指定する場合、.eslintrc.js を基準とする)
|
|
190
|
+
// '@/hoge/fuga': true // ['abc', 'def'] と指定すると個別に指定
|
|
191
|
+
// }
|
|
192
|
+
// },
|
|
193
|
+
// additionalBarrelFileNames: ['client'], // Next.jsなどでclient.tsをbarrelとして扱う
|
|
194
|
+
}
|
|
60
195
|
],
|
|
61
196
|
},
|
|
62
197
|
}
|