Guides: Migrate from eslint-plugin-check-file: Move file and folder naming rules from eslint-plugin-check-file to mustBeNamed and mustNotExist rules. # Migrate from eslint-plugin-check-file > Move file and folder naming rules from eslint-plugin-check-file to mustBeNamed and mustNotExist rules. eslint-plugin-check-file checks the names of files and folders. Archangel checks them with `mustBeNamed`, and checks where files may be with `mustNotExist`. This guide moves four common check-file rules. ## The config before eslint.config.js ```js import checkFile from 'eslint-plugin-check-file'; export default [ { files: ['src/**/*.{ts,tsx}'], plugins: { 'check-file': checkFile }, rules: { 'check-file/filename-naming-convention': [ 'error', { 'src/**/*.{ts,tsx}': 'KEBAB_CASE' }, { ignoreMiddleExtensions: true }, ], 'check-file/folder-naming-convention': ['error', { 'src/**/': 'KEBAB_CASE' }], 'check-file/filename-blocklist': ['error', { '**/*.util.ts': '*.helpers.ts' }], 'check-file/folder-match-with-fex': ['error', { '*.test.ts': '**/__tests__/' }], }, }, ]; ``` ## Map each rule | eslint-plugin-check-file | archangel | | ------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- | | `filename-naming-convention` | A rule on `files` with `mustBeNamed` and a style. | | `folder-naming-convention` | A rule on `folders` with `mustBeNamed` and a style. | | `KEBAB_CASE`, `CAMEL_CASE`, `PASCAL_CASE`, `SNAKE_CASE`, `SCREAMING_SNAKE_CASE` | `'kebab-case'`, `'camelCase'`, `'PascalCase'`, `'snake_case'`, `'SCREAMING_SNAKE_CASE'` | | `ignoreMiddleExtensions: true` | The default. A style reads the name up to the first dot, so `money.util.ts` is checked as `money`. | | A glob as the convention, such as `*.view` | A name pattern, or a list of them: `mustBeNamed: ['*.view', '*.container']`. | | `filename-blocklist` | A rule on the blocked files with `mustNotExist: true`, and the new name in `because`. | | `folder-match-with-fex` | A rule with `mustNotExist: true` on the files outside their folder: `{ all: ['**/*.test.ts', { not: '**/__tests__/**' }] }`. | | `no-index` | A rule on `**/index.ts` with `mustNotExist: true`. | ## The config after archangel.config.ts ```ts import { defineConfig } from '@enhance-eng/archangel'; export default defineConfig({ rules: ({ rule }) => [ rule('filename-naming-convention', { files: 'src/**/*.{ts,tsx}', mustBeNamed: 'kebab-case', examples: { rejected: ['src/lib/formatDate.ts'] }, }), rule('folder-naming-convention', { folders: ['src/**', '!src/**/__tests__'], mustBeNamed: 'kebab-case', examples: { rejected: ['src/userProfile/index.ts'] }, }), rule('filename-blocklist', { files: '**/*.util.ts', mustNotExist: true, because: 'Name it *.helpers.ts.', examples: { rejected: ['src/lib/date.util.ts'] }, }), rule('folder-match-with-fex', { files: { all: ['**/*.test.ts', { not: '**/__tests__/**' }] }, mustNotExist: true, because: 'A test file goes in a __tests__ folder.', examples: { rejected: ['src/lib/date.test.ts'] }, }), ], }); ``` * The folder rule leaves out `__tests__` with a `!` pattern, as in `.gitignore`. `__tests__` is not kebab-case, so the rule would refuse it. * `mustNotExist` reports each file that its `files` find. Write the set of files that must not exist. * Each rule has a rejected example on one line. For a naming rule, the one line is the path of one empty file. ## Run it 1. Prove the rules: Terminal ```ansi $ npx archangel test pass filename-naming-convention rejected #1 src/lib/formatDate.ts pass folder-naming-convention rejected #1 src/userProfile/index.ts pass filename-blocklist rejected #1 src/lib/date.util.ts pass folder-match-with-fex rejected #1 src/lib/date.test.ts 4 examples, none failed; 0 rules without a rejected example ``` 2. Check the repository: Terminal ```ansi $ npx archangel check error[must-not-exist]: src/lib/money.util.ts must not exist, because it is in **/*.util.ts --> src/lib/money.util.ts = help: move the file to where the architecture puts it, or delete it = note: rule: filename-blocklist = note: because: Name it *.helpers.ts. error[must-not-exist]: src/lib/parse-price.test.ts must not exist, because it is in all of (**/*.test.ts, not **/__tests__/**) --> src/lib/parse-price.test.ts = help: move the file to where the architecture puts it, or delete it = note: rule: folder-match-with-fex = note: because: A test file goes in a __tests__ folder. error[must-be-named]: the name of parsePrice.ts is parsePrice, which is not kebab-case; in kebab-case the file is parse-price.ts --> src/lib/parsePrice.ts = help: name it parse-price.ts = note: rule: filename-naming-convention checked 6 files and 4 imports: 3 problems For what a code means, run `archangel docs must-not-exist` or `archangel docs must-be-named`. ``` Each problem has the name to use. The style error shows the name in the correct style. ## Results that change * **A style checks the name up to the first dot.** Archangel checks `button` in `button.view.tsx`. A name pattern, such as `*.view`, reads the full name without the last extension, `button.view`. * **No rules for the first or last character.** Archangel has no rule for the first or the last character of a name. Write a name pattern, or a plugin condition. * **A name can use its folder.** A name pattern can use the name of the file or its folder in each style, for example `{folder-name}.test`. See [File and folder names](/archangel/guides/names/). A blocklist rule on a clean repository A `mustNotExist` rule on `files` that finds no file is not an error, because no file is the goal. So the blocklist rule stays correct after you rename the last blocked file.