Sets of files
Markdown for agentsA set of files says which files a rule is about. You write a set in a group, in a rule’s files,
on the other side of an import condition, in within, in stopAt, and in a table’s files.
The forms
Section titled “The forms”| You write | The set has |
|---|---|
'feature' |
the files of the part or group with this name |
'src/**/*.view.tsx' |
the files that the path pattern finds |
['app', 'feature'] |
the files in one or more of these sets |
{ any: ['app', 'feature'] } |
the files in one or more of these sets |
{ all: ['src/**', { not: 'test' }] } |
the files that are in each of these sets |
{ not: 'test' } |
each file except these files |
{ element: 'feature' } |
the files of the part feature |
{ element: 'feature', capture: { feature: 'login' } } |
the files of one instance of a part |
{ element: '*' } |
each file that is in a part |
{ directive: 'use client' } |
the files that start with this directive |
{ tag: '@side-effect-free' } |
the files whose comments before the first statement carry this JSDoc tag |
On the other side of an import condition, you can also write packages:
| You write | The other side has |
|---|---|
{ packages: ['react', 'react-dom'] } |
these packages and their subpaths |
{ packages: ['@radix-ui/*'] } |
each package in the scope |
{ packages: ['lodash-es/*'] } |
the subpaths of the package, such as lodash-es/get, and not its root |
{ packages: ['*'] } |
each package |
'driver' |
the packages of the externals set driver |
A name or a path pattern
Section titled “A name or a path pattern”Archangel reads a string in this order:
- When it is the name of a part, a group or an externals set, it means that name. The names of a
preset, such as
fsd/features, count too. - When it has a
/or a*, it is a path pattern. - Each other string is an error:
rule-unknown-element. The message shows the declared names nearest to it.
So mayNotImport: 'lodash' is an error, not a package. Write { packages: ['lodash'] }.
A kind is not a name here. A kind has a meaning only in its table.
Path patterns
Section titled “Path patterns”A pattern starts at the config folder. Archangel compares it with paths relative to the config
folder, with / between folders on each operating system.
| In a pattern | It matches |
|---|---|
** |
zero or more folders. It must be a full folder name. |
* |
zero or more characters in one folder name or file name |
{a,b} |
a or b |
{name} |
a capture: one or more characters in one folder name or file name |
Braces with a comma are alternatives. Braces with one name are a capture. A capture records the text that it matched. Read Captures and instances.
Archangel refuses a pattern with an empty folder name (src//x), a ** that is not a full folder
name (src/ui**/x), a capture without a name, or one capture name two times. The error is
pattern-invalid.
Directives
Section titled “Directives”{ directive: 'use client' } finds each file whose first statement is that directive. Use it for
React Server Components and Server Actions:
rule('client-has-no-db', { files: { directive: 'use client' }, mayNotImport: 'db', examples: { rejected: [{ 'src/view/a.tsx': "'use client';\nimport '../db/a';" }], },})Root files and ! patterns
Section titled “Root files and ! patterns”A pattern that starts with ./ names a path from the config folder. Write './app.config.ts' for
a file at the root, because 'app.config.ts' reads as the name of a part or a group.
In a part’s list, a pattern that starts with ! leaves those files out of the part. Write
pack: ['src/shared/{pack}/**', '!src/shared/widgets/**'] beside
widget: 'src/shared/widgets/{widget}/**', so that each widget is in the part widget only.
Package subpaths
Section titled “Package subpaths”A package name with a subpath names only those subpaths. This rule bans deep imports into
lodash-es and permits its root:
rule('no-deep-lodash', { files: 'shared', mayNotImport: { packages: ['lodash-es/*'] } }){ tag: '@side-effect-free' } finds each file whose comments before its first statement carry that
JSDoc tag, such as /** @side-effect-free */. A tag is the word that starts with @ at the start
of a comment line, after any *. A license comment above the docblock does not hide it, and a tag
in a comment after the first statement does not count. Use it to check what a tag that a bundler
acts on promises. This rule keeps tagged files from importing untagged ones:
rule('pure-imports-pure', { files: { tag: '@side-effect-free' }, mayOnlyImport: { tag: '@side-effect-free' } })A rule that selects files by directive or by tag cannot use a one-line example, because the text of the file decides the result.
A set that finds no file
Section titled “A set that finds no file”A part or a group that finds no file is an error, because a rule about an empty set can never find
a problem. The codes are element-empty and
selector-empty.
A preset part that finds no file is not an error, because most repositories use only some parts of a preset. Archangel lists it in the summary. Read Presets.