Skip to main content

Version 1.1

New Feature: Recursive Globs (**) in Module Paths

A ** segment in a module key matches zero or more directory segments, so modules at varying depths need a single key:

export const config: SheriffConfig = {
modules: {
'libs/**/feature-<name>': ['type:feature', 'feature:<name>'],
'libs/**/<domain>/api': ['type:api', 'domain:<domain>'],
},
};
  • ** must be a complete segment and matches zero segments too (libs/**/api also matches libs/api).
  • ** never captures a placeholder.
  • Discovery driven purely by ** skips node_modules and dot-directories; explicit segments still match them.
  • For file-level exports, a pattern without ** outranks any pattern with one.

See Recursive Globs for the full semantics.

New Feature: Single-File Modules

A module key whose last segment ends with a source-file extension defines one module per matching file:

export const config: SheriffConfig = {
modules: {
'src/app/stores/<name>.store.ts': ['type:store', 'store:<name>'],
},
};

Two stores in the same folder are now separate modules with their own tags and dependency rules. Placeholders capture inside the filename, ** works to the left of it, and file modules work in barrel mode too. A file module always exposes exactly its own file; exports on a file-module key is rejected with the new error SH-023.

See File Modules.

Fix: Raw Wildcards Match During Tagging

Module discovery matched a raw * in module keys, but tagging required an exact string match, so a wildcard-defined module existed but silently carried noTag. Tagging now applies the same single-segment wildcard semantics as discovery.

Fix: All Matching Module Patterns Are Followed

Config-based module discovery descended into only the first pattern matching a directory, silently losing sibling patterns and their modules (issue #56). Every matching pattern is now followed.