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 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.13.0",
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
- "gitHead": "75b2791f637c4769435be4f8cfe07cb2a2b5fa2d"
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
- return {
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
- }