Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/feature-sliced/steiger

Universal file structure and project architecture linter
https://github.com/feature-sliced/steiger

architecture folders imports linter naming-conventions

Last synced: 4 days ago
JSON representation

Universal file structure and project architecture linter

Awesome Lists containing this project

README

        

# Steiger

[![NPM Version](https://img.shields.io/npm/v/steiger)](https://www.npmjs.com/package/steiger)

Universal file structure and project architecture linter.

> [!NOTE]
> The project is in beta and in active development. Some APIs may change.

> [!NOTE]
> Version 0.5.0 introduced a new config file format. We have a codemod to automatically update your config, see the [migration guide](./MIGRATION_GUIDE.md).

## Features

- Built-in set of rules to validate adherence to [Feature-Sliced Design](https://feature-sliced.design/)
- Watch mode
- Rule configurability

## Installation

```bash
npm i -D steiger
```

## Usage

```bash
npx steiger ./src
```

To run in watch mode, add `-w`/`--watch` to the command:

```bash
npx steiger ./src --watch
```

## Configuration

Steiger is zero-config! If you don't want to disable certain rules, you can safely skip this section.

Steiger is configurable via `cosmiconfig`. That means that you can create a `steiger.config.ts` or `steiger.config.js` file in the root of your project to configure the rules. Import `{ defineConfig } from "steiger"` to get autocompletion.

The config file shape is highly inspired by ESLint's config file, so if you have configured ESLint before, you'll find it easy to configure Steiger.

### Example

```javascript
// ./steiger.config.js
import { defineConfig } from 'steiger'
import fsd from '@feature-sliced/steiger-plugin'

export default defineConfig([
...fsd.configs.recommended,
{
// disable the `public-api` rule for files in the Shared layer
files: ['./src/shared/**'],
rules: {
'fsd/public-api': 'off',
},
},
])
```

> [!TIP]
> If you want Steiger to ignore certain files, add an object like this to the config array:
>
> ```js
> defineConfig([, /* … */ { ignores: ['**/__mocks__/**'] }])
> ```

Comprehensive showcase of the config file syntax

```javascript
// ./steiger.config.ts
import { defineConfig } from 'steiger'
import fsd from '@feature-sliced/steiger-plugin'

export default defineConfig([
...fsd.configs.recommended,
{
// ignore all mock files for all rules
ignores: ['**/__mocks__/**'],
},
{
files: ['./src/shared/**'],
rules: {
// disable public-api rule for files in /shared folder
'fsd/public-api': 'off',
},
},
{
files: ['./src/widgets/**'],
ignores: ['**/discount-offers/**'],
rules: {
// disable no-segmentless-slices rule for all widgets except /discount-offers
'fsd/no-segmentless-slices': 'off',
},
},
])
```
[You can see more examples here](CONFIG_EXAMPLES.md)

### Migration from 0.4.0

Version 0.5.0 introduced a new config file format. Follow the [instructions](MIGRATION_GUIDE.md) to migrate your config file.

## Rules

Currently, Steiger is not extendable with more rules, though that will change in the near future. The built-in rules check for the project's adherence to [Feature-Sliced Design](https://feature-sliced.design/).


Rule
Description

ambiguous-slice-names Forbid slice names that that match some segment’s name in the Shared layer.
excessive-slicing Forbid having too many ungrouped slices or too many slices in a group.
forbidden-imports Forbid imports from higher layers and cross-imports between slices on the same layer.
inconsistent-naming Ensure that all entities are named consistently in terms of pluralization.
insignificant-slice Detect slices that have just one reference or no references to them at all.
no-layer-public-api Forbid index files on the layer level.
no-public-api-sidestep Forbid going around the public API of a slice to import directly from an internal module in a slice.
no-reserved-folder-names Forbid subfolders in segments that have the same name as other conventional segments.
no-segmentless-slices Forbid slices that don't have any segments.
no-segments-on-sliced-layers Forbid segments (like ui, lib, api ...) that appear directly in sliced layer folders (entities, features, ...)
no-ui-in-app Forbid having the ui segment on the App layer.
public-api Require slices (and segments on sliceless layers like Shared) to have a public API definition.
repetitive-naming Ensure that all entities are named consistently in terms of pluralization.
segments-by-purpose Discourage the use of segment names that group code by its essence, and instead encourage grouping by purpose
shared-lib-grouping Forbid having too many ungrouped modules in shared/lib.
typo-in-layer-name Ensure that all layers are named without any typos.
no-processes Discourage the use of the deprecated Processes layer.
import-locality Require that imports from the same slice be relative and imports from one slice to another be absolute.

## Contribution

Feel free to report an issue or open a discussion. Ensure you read our [Code of Conduct](CODE_OF_CONDUCT.md) first though :)

To get started with the codebase, see our [Contributing guide](CONTRIBUTING.md).

## Legal info

Project licensed under [MIT License](LICENSE.md). [Here's what it means](https://choosealicense.com/licenses/mit/)