Imports
Which code may import which code, in a table. Direct imports, chains of imports, the names that
an import brings in, and packages that package.json does not list.
mayImport('app', {
feature: ['shared'],
shared: [],
})
error[may-import]: feature may not import
another instance of feature
--> src/features/checkout/checkout.ts:1:27
= note: rule: app.feature
checked 5 files and 4 imports: 1 problem
A decision such as “features do not import each other” is easy to write in a document. It is also easy to break with one line in a large change. A reviewer sees the diff, not the graph of imports.
Archangel makes the decision a test. Give names to the parts of your code. Then write a table: each row is a part, and the list on the row is what that part may import.
import { defineConfig } from '@enhance-eng/archangel';
export default defineConfig({ parts: { feature: 'src/features/{feature}/**', shared: 'src/shared/**', }, rules: ({ mayImport, rule }) => [ mayImport('app', { feature: ['shared'], shared: [], }, { because: 'A feature changes alone. Code that two features need goes in shared.', }),
rule('no-react-in-shared', { files: 'shared', mayNotImport: { packages: ['react'] }, because: 'Shared code also runs on the server.', examples: { rejected: ['src/shared/money.ts imports react'], }, }), ],});The checkout feature imports a file inside the cart feature. Archangel shows where, why, and what to do:
$ npx archangel checkerror[may-import]: feature may not import another instance of feature, through "../cart/cart": feature may import only shared, and itself in the same instance --> src/features/checkout/checkout.ts:1:27 |1 | import { cartTotal } from '../cart/cart'; | ^^^^^^^^^^^^^^ feature may import only shared, and itself in the same instance | = help: remove the import, or move the code to a file whose row permits the import = note: rule: app.feature = note: because: A feature changes alone. Code that two features need goes in shared.
checked 5 files and 4 imports: 1 problemFor what a code means, run `archangel docs may-import`.Imports
Which code may import which code, in a table. Direct imports, chains of imports, the names that
an import brings in, and packages that package.json does not list.
Cycles
Files that import each other. Runtime imports count. Type imports count only when you say so.
Structure
Where files must be, which files a folder must contain, and which files must not exist.
Names and exports
The style of file and folder names, lists of permitted names, and what a file must export.
A rule with a wrong path finds no files. It then shows “no problems”, the same as a rule that works. Archangel does not let this occur in silence:
archangel test
fails when the rule does not reject it.archangel rules shows each rule as a sentence, with the files and imports that it judged, and
the files that no rule judges.A Rust core reads each file one time. The chart shows the time to check the same 400 rules on a 9,800-file monorepo, on a laptop. Without archangel, these rules need three tools. The editor shows the result of a change in about 13 milliseconds.