Skip to content

Migrate from eslint-plugin-check-file

Markdown for agents

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.

eslint.config.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__/' }],
},
},
];
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.
archangel.config.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.
  1. Prove the rules:

    Terminal
    $ 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
    $ 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.

  • 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.