eslint-plugin-smarthr 6.18.0 → 6.19.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 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.19.0](https://github.com/kufu/tamatebako/compare/eslint-plugin-smarthr-v6.18.0...eslint-plugin-smarthr-v6.19.0) (2026-06-10)
6
+
7
+
8
+ ### Features
9
+
10
+ * require-barrel-import に同一ディレクトリ内の重複export検出機能を追加 ([#1350](https://github.com/kufu/tamatebako/issues/1350)) ([313449a](https://github.com/kufu/tamatebako/commit/313449a088aec3fa984f8bf1ba87e24bad1f10d6))
11
+
5
12
  ## [6.18.0](https://github.com/kufu/tamatebako/compare/eslint-plugin-smarthr-v6.17.0...eslint-plugin-smarthr-v6.18.0) (2026-06-09)
6
13
 
7
14
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-smarthr",
3
- "version": "6.18.0",
3
+ "version": "6.19.0",
4
4
  "author": "SmartHR",
5
5
  "license": "MIT",
6
6
  "description": "A sharable ESLint plugin for SmartHR",
@@ -142,17 +142,17 @@ export { Header } from './Header' // server component
142
142
  export { ButtonIcon } from './ButtonIcon' // client component
143
143
  ```
144
144
 
145
- **パターンB: 両方のbarrelから同じファイルをexportしている(間接的な問題)**
145
+ **パターンB: 同じファイルから同じものを複数のbarrelでre-exportしている(重複export)**
146
146
 
147
- このパターンはこのルールでは検出されませんが、本質的に同じ問題です:
147
+ このルールは同じディレクトリの複数のbarrelファイルから同じファイルの同じものをre-exportしているパターンも検出します:
148
148
 
149
149
  ```typescript
150
- // ❌ 両方から同じファイルをexportしている
150
+ // ❌ 同じファイルから同じものを複数のbarrelでre-exportしている
151
151
  // components/Button/index.ts
152
- export { ButtonIcon } from './ButtonIcon' // ← 両方からexport(間接的な問題)
152
+ export { ButtonIcon } from './ButtonIcon' // ← エラー: client.tsでもexportされています
153
153
 
154
154
  // components/Button/client.ts
155
- export { ButtonIcon } from './ButtonIcon' // ← 両方からexport(間接的な問題)
155
+ export { ButtonIcon } from './ButtonIcon' // ← エラー: index.tsでもexportされています
156
156
 
157
157
  // ✅ 修正後: どちらか一方からのみexport
158
158
  // components/Button/index.ts
@@ -201,6 +201,115 @@ export { Button } from './ButtonBase'
201
201
 
202
202
  ただし、この方法は稀なケースです。ほとんどの場合は方法1または方法2で解決できます。
203
203
 
204
+ ## 同じディレクトリの複数バレルファイル間での重複export検出
205
+
206
+ 同じディレクトリに複数のバレルファイル(例: `index.ts` と `client.ts`)が存在する場合、同じファイルから同じものを複数のバレルファイルでre-exportすることを禁止します。
207
+
208
+ ### なぜ重複exportを禁止する必要があるのか
209
+
210
+ バレルファイルを分けている場合、それぞれに異なる役割があるはずです。同じファイルから同じものを複数のバレルファイルでre-exportすると、以下の問題が発生します:
211
+
212
+ 1. **意図的な分離の崩壊**: server/client、public/internalなどの分離が無意味になる
213
+ 2. **利用者の混乱**: どちらのbarrelからimportすべきか判断できない
214
+ 3. **保守性の低下**: 同じコンポーネントが複数箇所から提供され、管理が煩雑になる
215
+
216
+ ### ❌ 検出されるエラーケース
217
+
218
+ ```typescript
219
+ // components/Button/index.ts
220
+ export { ButtonIcon } from './ButtonIcon' // ❌ エラー
221
+
222
+ // components/Button/client.ts
223
+ export { ButtonIcon } from './ButtonIcon' // ❌ エラー
224
+
225
+ // エラーメッセージ:
226
+ // 'ButtonIcon' は client.ts でも export されています。
227
+ // 同じファイルから同じものを複数のバレルファイルで re-export することは禁止されています。
228
+ ```
229
+
230
+ 複数の識別子が重複している場合、それぞれに対してエラーが報告されます:
231
+
232
+ ```typescript
233
+ // services/index.ts
234
+ export { api, client } from './modules' // ❌ 両方ともエラー
235
+
236
+ // services/client.ts
237
+ export { api, client } from './modules' // ❌ 両方ともエラー
238
+ ```
239
+
240
+ エイリアス(`as`)を使用している場合でも、**元のソースファイルと元の識別子名**でチェックされます。エイリアス後の名前は重複チェックには使用されません:
241
+
242
+ ```typescript
243
+ // ❌ エラー: 同じファイルから同じ識別子をimport
244
+ // components/index.ts
245
+ export { Button as MyButton } from './Button' // ❌ エラー
246
+
247
+ // components/client.ts
248
+ export { Button } from './Button' // ❌ エラー
249
+ // './Button' から 'Button' を import している点が重複
250
+
251
+ // ✅ OK: 異なるファイルからなので重複ではない
252
+ // components/index.ts
253
+ export { Button } from './Component' // ✅ OK
254
+
255
+ // components/client.ts
256
+ export { Button } from './Button' // ✅ OK
257
+ // 異なるソースファイル(./Component と ./Button)なので重複ではない
258
+ ```
259
+
260
+ ### ✅ 正しい修正方法
261
+
262
+ #### 方法1: どちらか一方のbarrelからのみexport(推奨)
263
+
264
+ ```typescript
265
+ // components/Button/index.ts
266
+ export { ServerButton } from './ServerButton' // server component
267
+
268
+ // components/Button/client.ts
269
+ export { ButtonIcon } from './ButtonIcon' // client component
270
+ // 異なる識別子をexportしているのでOK
271
+ ```
272
+
273
+ #### 方法2: export * は重複チェック対象外
274
+
275
+ `export * from` はすべてをre-exportする意図が明確なため、重複チェックの対象外です:
276
+
277
+ ```typescript
278
+ // ui/index.ts
279
+ export { Button } from './Button'
280
+
281
+ // ui/client.ts
282
+ export * from './components' // OK: export * は重複チェック対象外
283
+ ```
284
+
285
+ ただし、明示的なnamed exportは推奨されます。
286
+
287
+ ### よくある発生パターン
288
+
289
+ このエラーが発生する典型的なケース:
290
+
291
+ 1. 最初は `index.ts` に全てのexportが混在していた
292
+ 2. 後から分離の必要性が生じ、`client.ts` を作成した
293
+ 3. client componentを `client.ts` に移動したが、`index.ts` からのexportを削除し忘れた
294
+
295
+ ```typescript
296
+ // 修正前: 削除し忘れ
297
+ // index.ts
298
+ export { ServerComponent } from './ServerComponent'
299
+ export { ClientComponent } from './ClientComponent' // ← 削除し忘れ
300
+
301
+ // client.ts
302
+ export { ClientComponent } from './ClientComponent' // ← 重複
303
+
304
+ // 修正後
305
+ // index.ts
306
+ export { ServerComponent } from './ServerComponent'
307
+ // ClientComponent の export を削除
308
+
309
+ // client.ts
310
+ export { ClientComponent } from './ClientComponent'
311
+ ```
312
+
204
313
  ## バレルファイルの純粋性チェック
205
314
 
206
315
  バレルファイル(index.ts、client.ts等)は**設置されたディレクトリ外へのexportが責務**です。それ以外の実装(import文、変数定義、関数定義など)は禁止されます。