Skip to content
LogoLogo

folder-structure

Category: nursery. Default: off. Fixable: no. Since: 0.1.0.

What it does

Checks the shape of the file tree: the files that a folder must have, the names that it can have, and the case of its names. The rule looks at all files in the entry folders, not only at modules. For the folders above the entry folders, such as the root folder, it knows their own files and folders, but not what is inside the other folders. It does not check those other folders.

Why is this bad?

A project that has a convention for its folders needs a check for it. Without the check, the convention drifts: a page has no owner file, or a helper folder grows in the wrong place.

Options

  • folders: a list of entries. Each entry has a path and at least one of the other keys.
    • path: globs of the folders to check. {name} captures a path segment. A glob matches only the folder it names, so src/pages/{page} does not match src/pages/a/components. A glob can also match a file, such as src/components/**/{c}.tsx. Then the checks apply to the folder of the file. A glob that starts with ! removes folders from the match.
    • require: globs of the files and folders that the folder must have. A glob is relative to the folder and can contain /. {name} stands for the capture of path, and path must capture it. {a,b} means one of a and b.
    • allow: globs of the names that the files and folders directly in the folder can have. Deeper levels need their own entry. A glob that starts with ! forbids a name. A list of only such globs allows every other name.
    • case: kebab-case, camel-case, pascal-case or snake-case. The rule checks the name of each file and folder directly in the folder, before its first ..
    • message: Oxcruise shows this text instead of the generic message.

When several entries match one folder, all of them apply. To make an exception for one folder, narrow path with a glob that starts with !. To switch the rule off for an area, use overrides.

Ignoring a violation

A violation about a missing file, or about a file that is not a module, has no place for a comment. Change the config file for these. A // oxcruise-ignore-file folder-structure comment in a module silences the violations about that module.

Example

Every page has an owner file, a module has no utils folder, and components have a test next to them:

{ "folders": [
  { "path": "src/pages/{page}", "require": ["codeowners.ts", "index.{ts,tsx}"] },
  { "path": "src/modules/{m}", "allow": "!utils", "message": "Put shared helpers in src/lib." },
  { "path": "src/components", "case": "pascal-case" },
  { "path": ["src/components/**/{c}.tsx", "!**/*.{test,stories}.tsx"], "require": "{c}.test.tsx" }
] }

Configure the rule

{
  "rules": {
    "folder-structure": {
      "level": "error",
      "folders": [
        {
          "path": "src/pages/{page}",
          "require": [
            "codeowners.ts",
            "index.{ts,tsx}"
          ]
        },
        {
          "path": "src/modules/{m}",
          "allow": "!utils",
          "message": "Put shared helpers in src/lib."
        },
        {
          "path": "src/components",
          "case": "pascal-case"
        },
        {
          "path": [
            "src/components/**/{c}.tsx",
            "!**/*.{test,stories}.tsx"
          ],
          "require": "{c}.test.tsx"
        }
      ]
    }
  }
}

The object has the level first, then the options of the rule.