archprint 0.8.2 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +21 -0
- package/README.md +88 -11
- package/dist/cli/adopted-rules.d.ts +49 -0
- package/dist/cli/adopted-rules.d.ts.map +1 -0
- package/dist/cli/adopted-rules.js +159 -0
- package/dist/cli/adopted-rules.js.map +1 -0
- package/dist/cli/check-diff.d.ts +19 -0
- package/dist/cli/check-diff.d.ts.map +1 -0
- package/dist/cli/check-diff.js +41 -0
- package/dist/cli/check-diff.js.map +1 -0
- package/dist/cli/check-evaluate.d.ts +10 -0
- package/dist/cli/check-evaluate.d.ts.map +1 -0
- package/dist/cli/check-evaluate.js +83 -0
- package/dist/cli/check-evaluate.js.map +1 -0
- package/dist/cli/check-git.d.ts +12 -0
- package/dist/cli/check-git.d.ts.map +1 -0
- package/dist/cli/check-git.js +87 -0
- package/dist/cli/check-git.js.map +1 -0
- package/dist/cli/check-locate.d.ts +3 -0
- package/dist/cli/check-locate.d.ts.map +1 -0
- package/dist/cli/check-locate.js +29 -0
- package/dist/cli/check-locate.js.map +1 -0
- package/dist/cli/check.d.ts +41 -0
- package/dist/cli/check.d.ts.map +1 -0
- package/dist/cli/check.js +230 -0
- package/dist/cli/check.js.map +1 -0
- package/dist/cli/generate.d.ts +5 -0
- package/dist/cli/generate.d.ts.map +1 -1
- package/dist/cli/generate.js +37 -11
- package/dist/cli/generate.js.map +1 -1
- package/dist/cli/git-env.d.ts +2 -0
- package/dist/cli/git-env.d.ts.map +1 -0
- package/dist/cli/git-env.js +14 -0
- package/dist/cli/git-env.js.map +1 -0
- package/dist/cli/layout.d.ts +2 -0
- package/dist/cli/layout.d.ts.map +1 -1
- package/dist/cli/layout.js +3 -1
- package/dist/cli/layout.js.map +1 -1
- package/dist/cli/migrate.d.ts.map +1 -1
- package/dist/cli/migrate.js +1 -0
- package/dist/cli/migrate.js.map +1 -1
- package/dist/cli/program.d.ts.map +1 -1
- package/dist/cli/program.js +52 -0
- package/dist/cli/program.js.map +1 -1
- package/dist/cli/recommend.d.ts +2 -0
- package/dist/cli/recommend.d.ts.map +1 -1
- package/dist/cli/recommend.js +8 -2
- package/dist/cli/recommend.js.map +1 -1
- package/dist/cli/report.d.ts +1 -1
- package/dist/cli/report.d.ts.map +1 -1
- package/dist/cli/report.js +26 -18
- package/dist/cli/report.js.map +1 -1
- package/dist/cli/rule-guidance.js +3 -3
- package/dist/cli/rule-guidance.js.map +1 -1
- package/dist/cli/scan.d.ts.map +1 -1
- package/dist/cli/scan.js +6 -3
- package/dist/cli/scan.js.map +1 -1
- package/dist/detector/marker-inference.d.ts +3 -0
- package/dist/detector/marker-inference.d.ts.map +1 -1
- package/dist/detector/marker-inference.js +26 -18
- package/dist/detector/marker-inference.js.map +1 -1
- package/dist/detector/pattern-detector.d.ts +1 -0
- package/dist/detector/pattern-detector.d.ts.map +1 -1
- package/dist/detector/pattern-detector.js +7 -4
- package/dist/detector/pattern-detector.js.map +1 -1
- package/dist/generator/public-api-emitters.d.ts +1 -0
- package/dist/generator/public-api-emitters.d.ts.map +1 -1
- package/dist/generator/public-api-emitters.js +2 -1
- package/dist/generator/public-api-emitters.js.map +1 -1
- package/dist/generator/rule-generator.d.ts.map +1 -1
- package/dist/generator/rule-generator.js +51 -29
- package/dist/generator/rule-generator.js.map +1 -1
- package/dist/mcp/remote/server.d.ts +21 -0
- package/dist/mcp/remote/server.d.ts.map +1 -1
- package/dist/mcp/remote/server.js +12 -0
- package/dist/mcp/remote/server.js.map +1 -1
- package/dist/mcp/server.d.ts +24 -3
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +24 -3
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/tools.d.ts.map +1 -1
- package/dist/mcp/tools.js +12 -1
- package/dist/mcp/tools.js.map +1 -1
- package/dist/scanner/file-walker.d.ts +5 -0
- package/dist/scanner/file-walker.d.ts.map +1 -1
- package/dist/scanner/file-walker.js +8 -2
- package/dist/scanner/file-walker.js.map +1 -1
- package/dist/scanner/import-graph.d.ts +2 -0
- package/dist/scanner/import-graph.d.ts.map +1 -1
- package/dist/scanner/import-graph.js +1 -1
- package/dist/scanner/import-graph.js.map +1 -1
- package/package.json +3 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
# archprint
|
|
2
2
|
|
|
3
|
+
## 0.9.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- Add `archprint check`, which reports only the violations a change introduces, compared with a base branch or commit, for the rules your team adopted with `init` or `generate`. It works in any CI. On GitHub, `--format github` shows each finding inline on the pull request, with its evidence, plus a step summary that also counts the violations the change fixed. It warns by default; `--fail-on new` fails the job so you can make it a required status check. `--format json` and exit codes (`0` ok, `1` new violations, `2` the CI setup is wrong) cover other CI systems.
|
|
8
|
+
|
|
9
|
+
`init` and `generate` now also write `.archprint/rules.json`, the exact definition of each adopted mechanical rule, which `check` uses so it never re-infers a rule. If you set up archprint with 0.8.x or earlier, run `archprint generate` once; until then `check` reports that it did not run.
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- The same repository now gives the same output on every machine. archprint reads files in name order instead of the order the filesystem returns them, which differs between macOS and Linux, so an example exception or a generated fixture no longer changes between a laptop and CI.
|
|
14
|
+
- `generate --expand` now writes each forbidden-import rule's files from that rule. Before, the database rule (AP-001) got the UI rule's ESLint message, rule card text and fixtures, so its failing fixture imported a UI component that AP-001 never flags. Each rule's message now states the rule, its card lists what it forbids, and its failing fixture imports something the rule really reports: one of the repo's own exceptions when there is one, otherwise the database wrapper or component folder archprint found.
|
|
15
|
+
- The local MCP server now says plainly when it is given a repository URL instead of a directory, and points to `archprint mcp --http` for scanning a public repository by URL. Before, it reported a missing `tsconfig.json` under a path built from the URL. It also reads a `file://` URL as the local directory it names, and ignores spaces around a path.
|
|
16
|
+
- Plainer wording. The database and UI rules (AP-001, AP-002) now say "request handler" instead of "request-entry" or "server-entry" file, in scan output, ESLint messages, rule cards and fix guidance. `scan` prints each of these rules as a sentence followed by "N of M files it applies to follow it".
|
|
17
|
+
|
|
18
|
+
## 0.8.3
|
|
19
|
+
|
|
20
|
+
### Patch Changes
|
|
21
|
+
|
|
22
|
+
- The MCP server is ready for MCP directories. Each tool now has a human-readable title and is marked read-only and non-destructive, so clients can show it as safe to run (the remote `--http` tools are also marked as reaching the internet). The package declares its MCP Registry name, and every release publishes to the official MCP Registry automatically. `archprint scan` now labels each rule group the same way `init` and `recommend` do: dependency hygiene and dependency declaration read "review before enforcing", and circular dependencies read "report only". The README lists example prompts to ask your agent.
|
|
23
|
+
|
|
3
24
|
## 0.8.2
|
|
4
25
|
|
|
5
26
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -5,11 +5,12 @@
|
|
|
5
5
|
[](https://www.npmjs.com/package/archprint)
|
|
6
6
|
[](./LICENSE)
|
|
7
7
|
[](https://tommkruix.github.io/archprint/)
|
|
8
|
+
[](https://glama.ai/mcp/servers/Tommkruix/archprint)
|
|
8
9
|
|
|
9
10
|
**Mine the architecture rules your repo already enforces, with the evidence attached.**
|
|
10
11
|
|
|
11
12
|
**[Try it in your browser](https://stackblitz.com/github/Tommkruix/archprint-demo)**, nothing to install ·
|
|
12
|
-
[Quick start](#quick-start) · [Use with AI agents](#use-it-with-ai-coding-agents) · [Docs](https://tommkruix.github.io/archprint/)
|
|
13
|
+
[Quick start](#quick-start) · [Use in CI](#use-in-ci) · [Use with AI agents](#use-it-with-ai-coding-agents) · [Docs](https://tommkruix.github.io/archprint/)
|
|
13
14
|
|
|
14
15
|
## What it does, in plain words
|
|
15
16
|
|
|
@@ -27,6 +28,8 @@ instead of handing you a rulebook from somewhere else.
|
|
|
27
28
|
|
|
28
29
|
- **For developers and tech leads:** inferred, evidence-backed lint rules for ESLint and dependency-cruiser,
|
|
29
30
|
generated with `init`, connected with `wire`, and removed with `eject`.
|
|
31
|
+
- **For reviewers:** `archprint check` flags only the rule breaks a pull request introduces, inline on GitHub,
|
|
32
|
+
never the existing backlog.
|
|
30
33
|
- **For teams using AI coding agents:** Claude Code, Cursor and other agents can ask Archprint for the project's
|
|
31
34
|
rules, with the evidence, before they write code.
|
|
32
35
|
- **For anyone evaluating a codebase:** a quick, honest picture of how a project is actually structured.
|
|
@@ -114,17 +117,27 @@ also accept the root and cover every app, while `init` and `generate` work on on
|
|
|
114
117
|
# 1. See the rules your code already follows, with the evidence. Changes nothing.
|
|
115
118
|
npx archprint scan .
|
|
116
119
|
|
|
117
|
-
# 2.
|
|
120
|
+
# 2. Ask why one rule is trusted (use a rule label from the scan)
|
|
121
|
+
npx archprint explain AP-001 .
|
|
122
|
+
|
|
123
|
+
# 3. Set up enforcement for the rules your code already follows cleanly,
|
|
118
124
|
# and record what to review or adopt next in .archprint/config.json
|
|
119
125
|
npx archprint init .
|
|
120
126
|
|
|
121
|
-
#
|
|
127
|
+
# 4. Connect the generated rules to your ESLint / dependency-cruiser config (one managed line)
|
|
122
128
|
npx archprint wire
|
|
123
129
|
|
|
124
|
-
#
|
|
130
|
+
# 5. Run your linter as usual. Your code passes today; a new import that breaks a rule fails.
|
|
131
|
+
npx eslint .
|
|
132
|
+
|
|
133
|
+
# To undo everything, exactly:
|
|
125
134
|
npx archprint eject
|
|
126
135
|
```
|
|
127
136
|
|
|
137
|
+
**See it catch something.** After step 4, break a rule on purpose: for example, make a route file import your
|
|
138
|
+
database client directly, then run your linter. That is the whole loop the
|
|
139
|
+
[demo](https://stackblitz.com/github/Tommkruix/archprint-demo) walks through in the browser.
|
|
140
|
+
|
|
128
141
|
To keep it in the project instead of using `npx`: `npm install --save-dev archprint`.
|
|
129
142
|
|
|
130
143
|
More commands for a deliberate, step-by-step setup:
|
|
@@ -253,6 +266,9 @@ a tool you do not have. `--emit <eslint|dependency-cruiser|all>` forces the form
|
|
|
253
266
|
mechanical boundaries (public-API deep-import, test-isolation); the review-held ones (layer, role-layering,
|
|
254
267
|
feature-slice, app-isolation, entry-purity, dependency-internals, phantom deps) are added only with
|
|
255
268
|
`--include-structural`, after you review them.
|
|
269
|
+
- **`.archprint/rules.json`**: the exact definition of each mechanical rule you adopted, with the evidence
|
|
270
|
+
recorded at adoption and the resolution mode it was generated in. `archprint check` reads it, so a check never
|
|
271
|
+
re-infers a rule.
|
|
256
272
|
- **`.archprint/config.json`**: what is enforced, followed but only reported, held for review, and worth
|
|
257
273
|
adopting, plus the list of managed outputs `eject` removes.
|
|
258
274
|
- **A managed section in your `README.md`** summarizing what is enforced now, followed but only reported, held for
|
|
@@ -272,6 +288,45 @@ exactly. `generate --check` runs the generated ESLint rules against your repo an
|
|
|
272
288
|
can confirm before wiring. Upgrading from 0.5.x? `archprint migrate` moves an older `archprint-rules/` setup to
|
|
273
289
|
this layout and rewires your configs in place.
|
|
274
290
|
|
|
291
|
+
## Use in CI
|
|
292
|
+
|
|
293
|
+
`archprint check` reports only the violations a change **introduces**, compared with a base branch, for the rules
|
|
294
|
+
your team adopted with `init` or `generate`. The existing backlog never shows up, and every finding carries its
|
|
295
|
+
evidence. It works in any CI, and on GitHub it shows each finding inline on the pull request.
|
|
296
|
+
|
|
297
|
+
```yaml
|
|
298
|
+
# .github/workflows/archprint.yml
|
|
299
|
+
name: archprint
|
|
300
|
+
on: pull_request
|
|
301
|
+
permissions:
|
|
302
|
+
contents: read
|
|
303
|
+
jobs:
|
|
304
|
+
check:
|
|
305
|
+
runs-on: ubuntu-latest
|
|
306
|
+
steps:
|
|
307
|
+
- uses: actions/checkout@v5
|
|
308
|
+
with:
|
|
309
|
+
ref: ${{ github.event.pull_request.head.sha }}
|
|
310
|
+
fetch-depth: 0
|
|
311
|
+
- uses: actions/setup-node@v5
|
|
312
|
+
with:
|
|
313
|
+
node-version: 22
|
|
314
|
+
- run: npm ci
|
|
315
|
+
- run: npx archprint check --base ${{ github.event.pull_request.base.sha }} --format github
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
- **Warning by default.** Add `--fail-on new` to fail the job on a new violation, then mark the job a required
|
|
319
|
+
status check in your branch protection so a pull request that adds one can't merge.
|
|
320
|
+
- **Only adopted rules.** `check` reads `.archprint/rules.json`, written by `init` and `generate`, and checks only
|
|
321
|
+
the mechanical rules recorded there, never structural ones. Rules adopted in the same pull request are listed
|
|
322
|
+
but never counted against it.
|
|
323
|
+
- **Upgrading from 0.8.x or earlier:** run `archprint generate` once to write `rules.json`. Until you do, `check`
|
|
324
|
+
posts a notice that it did not run and exits 0.
|
|
325
|
+
- **Other CI systems:** `--format json` gives version-keyed output, and the exit code is the contract: `0` ok, `1`
|
|
326
|
+
new violations with `--fail-on new`, `2` the CI setup is wrong (for example a shallow clone without the base
|
|
327
|
+
commit). Check out the full history (`fetch-depth: 0` or your CI's equivalent).
|
|
328
|
+
- **Safe on pull requests from forks.** It needs only read access, uses no secrets, and never runs your code.
|
|
329
|
+
|
|
275
330
|
## MCP setup
|
|
276
331
|
|
|
277
332
|
`archprint mcp` runs Archprint as an [MCP](https://modelcontextprotocol.io) server over stdio, so an agent can ask
|
|
@@ -288,6 +343,13 @@ scan (for example `AP-002` or `env-access`). Point Claude Desktop, Claude Code,
|
|
|
288
343
|
}
|
|
289
344
|
```
|
|
290
345
|
|
|
346
|
+
**Things to ask your agent.** You do not name the tools; the agent picks them:
|
|
347
|
+
|
|
348
|
+
- "What architecture rules does this repo already follow?"
|
|
349
|
+
- "Which file breaks the env-access rule, and how should I fix it?"
|
|
350
|
+
- "I am adding a new API route. What rules should it follow in this codebase?"
|
|
351
|
+
- "Which rules should we enforce now, and which are worth adopting?"
|
|
352
|
+
|
|
291
353
|
**Your code stays on your machine.** This default is a local server: it reads your local checkout, so it is the
|
|
292
354
|
one to use for private code, and your source never leaves your machine, whichever git host you use.
|
|
293
355
|
|
|
@@ -310,6 +372,15 @@ comes from nvm or Homebrew. A full path to `npx` alone is not enough, because `n
|
|
|
310
372
|
|
|
311
373
|
Starting the editor from a terminal also works, because it then inherits your shell's `PATH`.
|
|
312
374
|
|
|
375
|
+
**One-line installs.** In Claude Code:
|
|
376
|
+
|
|
377
|
+
```bash
|
|
378
|
+
claude mcp add archprint -- npx -y archprint mcp
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
In Cursor, put the JSON above in `.cursor/mcp.json` in your project (or `~/.cursor/mcp.json` for every project),
|
|
382
|
+
then enable **archprint** under **Settings > MCP**.
|
|
383
|
+
|
|
313
384
|
**Scanning a public repo by URL.** `archprint mcp --http` runs a remote server instead. It clones the repo shallow
|
|
314
385
|
to a temp dir, runs the same read-only analysis, returns the result, and deletes the clone (only public
|
|
315
386
|
`github.com`, `gitlab.com`, and `bitbucket.org` URLs; nothing is written or kept). The tools then take a `repo` URL
|
|
@@ -362,6 +433,9 @@ reachability) and knip (dead code); rather than compete, it writes the rules it
|
|
|
362
433
|
`--only <family>` and `--rules <ids>` narrow the output, `--check` runs the generated rules against your repo,
|
|
363
434
|
`--readme` adds the README section, `--expand` also writes the per-family files, cards, fixtures and graph, and
|
|
364
435
|
`--rule <id>` emits one reviewed rule. Also `--include-structural`, `--no-graph`, `--out <dir>`, `--fast`.
|
|
436
|
+
- **`archprint check [path]`**: reports the violations of your adopted rules that a change introduces, compared
|
|
437
|
+
with `--base <branch or commit>`. Warning only unless `--fail-on new`. `--format text|json|github`,
|
|
438
|
+
`--out <dir>`. See [Use in CI](#use-in-ci).
|
|
365
439
|
- **`archprint wire`**: references the generated rules from the enforcement tools your repo uses (flat eslint
|
|
366
440
|
config, `.dependency-cruiser.json`) through a managed, reversible reference. `--out <dir>`, `--dry-run`.
|
|
367
441
|
- **`archprint eject`**: removes Archprint's generated files, its config, the managed README section, and any
|
|
@@ -372,8 +446,9 @@ reachability) and knip (dead code); rather than compete, it writes the rules it
|
|
|
372
446
|
`scan`, `recommend`, and `explain` tools. Serves over stdio by default; `--http` runs a remote server that scans
|
|
373
447
|
a public repo by URL.
|
|
374
448
|
|
|
375
|
-
`scan --json` and `
|
|
376
|
-
`0` on success, `1` on error
|
|
449
|
+
`scan --json`, `recommend --json` and `check --format json` emit stable, version-keyed JSON for scripting. Exit
|
|
450
|
+
codes are the contract: `0` on success, `1` on error (for `check`: new violations with `--fail-on new`), `2` for a
|
|
451
|
+
`check` that could not run because of the CI setup.
|
|
377
452
|
|
|
378
453
|
## Example on a real repo
|
|
379
454
|
|
|
@@ -385,7 +460,8 @@ Workspace aliases: 18 resolved
|
|
|
385
460
|
|
|
386
461
|
GENERATED RULES
|
|
387
462
|
AP-002 no-ui-layer-in-server-entry confidence 97%
|
|
388
|
-
|
|
463
|
+
A request handler must not import UI components.
|
|
464
|
+
Evidence: 216 of 217 files it applies to follow it (99.5%)
|
|
389
465
|
Exceptions: 1
|
|
390
466
|
|
|
391
467
|
LAYER BOUNDARIES (review before enforcing)
|
|
@@ -419,10 +495,11 @@ were inferred from.
|
|
|
419
495
|
- **Validated at scale:** `scan` and `recommend` ran over a corpus of 92,861 public TypeScript repositories (61,690
|
|
420
496
|
apps) with zero crashes; 91 repos (0.1%) could not be fetched or timed out. The full `init`/`wire`/`eject`
|
|
421
497
|
round-trip ran clean on a 2,000-repo stratified sample.
|
|
422
|
-
- **Production-ready today:** `scan` and `recommend`, and auto-enforcement of the
|
|
423
|
-
self-consistency check at generate time, an `init` scaffolder for fresh repos, and
|
|
424
|
-
React, Angular, Vue, and Svelte. The engine (twenty detectors, the confidence gate, and
|
|
425
|
-
self-contained ESLint file, dependency-cruiser, ts-arch, and the layer graph) is in place and
|
|
498
|
+
- **Production-ready today:** `scan` and `recommend`, `check` for pull requests, and auto-enforcement of the
|
|
499
|
+
mechanical families, with a self-consistency check at generate time, an `init` scaffolder for fresh repos, and
|
|
500
|
+
framework coverage across React, Angular, Vue, and Svelte. The engine (twenty detectors, the confidence gate, and
|
|
501
|
+
emitters for a self-contained ESLint file, dependency-cruiser, ts-arch, and the layer graph) is in place and
|
|
502
|
+
tested.
|
|
426
503
|
- **Still ahead:** hardening the structural families toward auto-enforcement (a real per-file role-confidence
|
|
427
504
|
measure, layer cohesion, role-classifier ordering).
|
|
428
505
|
- **Versioning is still 0.x,** so the CLI surface and rule format can refine between minor versions. That is a
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { Role } from '../scanner/role-classifier.js';
|
|
2
|
+
import type { ScannedPattern, ScanResult } from './scan.js';
|
|
3
|
+
export declare const RULES_FILE = "rules.json";
|
|
4
|
+
export declare const RULES_FORMAT = 1;
|
|
5
|
+
export type ResolutionMode = 'deep' | 'fast';
|
|
6
|
+
export interface AdoptionEvidence {
|
|
7
|
+
conforming: number;
|
|
8
|
+
total: number;
|
|
9
|
+
floor: number;
|
|
10
|
+
}
|
|
11
|
+
interface RuleBase {
|
|
12
|
+
id: string;
|
|
13
|
+
statement: string;
|
|
14
|
+
mode: ResolutionMode;
|
|
15
|
+
evidence: AdoptionEvidence;
|
|
16
|
+
}
|
|
17
|
+
export interface ForbiddenImportRule extends RuleBase {
|
|
18
|
+
family: 'forbidden-imports';
|
|
19
|
+
roles: Role[];
|
|
20
|
+
forbidden: {
|
|
21
|
+
source: string;
|
|
22
|
+
flags: string;
|
|
23
|
+
}[];
|
|
24
|
+
}
|
|
25
|
+
export interface PublicApiRule extends RuleBase {
|
|
26
|
+
family: 'public-api';
|
|
27
|
+
dir: string;
|
|
28
|
+
}
|
|
29
|
+
export interface SingleFamilyRule extends RuleBase {
|
|
30
|
+
family: 'test-isolation' | 'console-isolation' | 'import-style';
|
|
31
|
+
}
|
|
32
|
+
export type AdoptedRule = ForbiddenImportRule | PublicApiRule | SingleFamilyRule;
|
|
33
|
+
export interface AdoptedRules {
|
|
34
|
+
format: typeof RULES_FORMAT;
|
|
35
|
+
archprintVersion: string;
|
|
36
|
+
rules: AdoptedRule[];
|
|
37
|
+
}
|
|
38
|
+
export declare function forbiddenImportRule(pattern: ScannedPattern, mode: ResolutionMode): AdoptedRule;
|
|
39
|
+
export declare function testIsolationRule(scan: ScanResult): AdoptedRule;
|
|
40
|
+
export declare function consoleIsolationRule(scan: ScanResult): AdoptedRule;
|
|
41
|
+
export declare function importStyleRule(scan: ScanResult): AdoptedRule;
|
|
42
|
+
export declare function publicApiRules(scan: ScanResult): AdoptedRule[];
|
|
43
|
+
export declare function writeAdoptedRules(outDir: string, rules: readonly AdoptedRule[], archprintVersion: string): string;
|
|
44
|
+
export declare class InvalidRulesError extends Error {
|
|
45
|
+
}
|
|
46
|
+
export declare function readAdoptedRules(outDir: string): AdoptedRules | null;
|
|
47
|
+
export declare function ruleDefinitionKey(rule: AdoptedRule): string;
|
|
48
|
+
export {};
|
|
49
|
+
//# sourceMappingURL=adopted-rules.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adopted-rules.d.ts","sourceRoot":"","sources":["../../src/cli/adopted-rules.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,+BAA+B,CAAC;AAG1D,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAE5D,eAAO,MAAM,UAAU,eAAe,CAAC;AACvC,eAAO,MAAM,YAAY,IAAI,CAAC;AAE9B,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,MAAM,CAAC;AAE7C,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAED,UAAU,QAAQ;IAChB,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,cAAc,CAAC;IACrB,QAAQ,EAAE,gBAAgB,CAAC;CAC5B;AAED,MAAM,WAAW,mBAAoB,SAAQ,QAAQ;IACnD,MAAM,EAAE,mBAAmB,CAAC;IAC5B,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,SAAS,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAChD;AAED,MAAM,WAAW,aAAc,SAAQ,QAAQ;IAC7C,MAAM,EAAE,YAAY,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,gBAAiB,SAAQ,QAAQ;IAChD,MAAM,EAAE,gBAAgB,GAAG,mBAAmB,GAAG,cAAc,CAAC;CACjE;AAED,MAAM,MAAM,WAAW,GAAG,mBAAmB,GAAG,aAAa,GAAG,gBAAgB,CAAC;AAEjF,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,OAAO,YAAY,CAAC;IAC5B,gBAAgB,EAAE,MAAM,CAAC;IACzB,KAAK,EAAE,WAAW,EAAE,CAAC;CACtB;AAQD,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,cAAc,EAAE,IAAI,EAAE,cAAc,GAAG,WAAW,CAW9F;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,UAAU,GAAG,WAAW,CAS/D;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,UAAU,GAAG,WAAW,CASlE;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,UAAU,GAAG,WAAW,CAS7D;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,UAAU,GAAG,WAAW,EAAE,CAW9D;AAED,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,SAAS,WAAW,EAAE,EAC7B,gBAAgB,EAAE,MAAM,GACvB,MAAM,CAOR;AAED,qBAAa,iBAAkB,SAAQ,KAAK;CAAG;AAyD/C,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,CAmBpE;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,WAAW,GAAG,MAAM,CAc3D"}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import * as path from 'node:path';
|
|
3
|
+
import { publicApiRuleName } from '../generator/public-api-emitters.js';
|
|
4
|
+
import { FAMILY_STATEMENTS } from './rule-statements.js';
|
|
5
|
+
export const RULES_FILE = 'rules.json';
|
|
6
|
+
export const RULES_FORMAT = 1;
|
|
7
|
+
const evidenceOf = (gate, total, violating) => ({
|
|
8
|
+
conforming: total - violating,
|
|
9
|
+
total,
|
|
10
|
+
floor: gate.conditions.confidence.value,
|
|
11
|
+
});
|
|
12
|
+
export function forbiddenImportRule(pattern, mode) {
|
|
13
|
+
const { config, result } = pattern;
|
|
14
|
+
return {
|
|
15
|
+
id: config.id,
|
|
16
|
+
family: 'forbidden-imports',
|
|
17
|
+
statement: config.description,
|
|
18
|
+
mode,
|
|
19
|
+
roles: [...config.roles],
|
|
20
|
+
forbidden: config.forbidden.map((marker) => ({ source: marker.source, flags: marker.flags })),
|
|
21
|
+
evidence: evidenceOf(result.gate, result.stats.roleFileCount, result.stats.violatingFileCount),
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
export function testIsolationRule(scan) {
|
|
25
|
+
const analysis = scan.testIsolation;
|
|
26
|
+
return {
|
|
27
|
+
id: 'test-isolation',
|
|
28
|
+
family: 'test-isolation',
|
|
29
|
+
statement: FAMILY_STATEMENTS['test-isolation'],
|
|
30
|
+
mode: 'fast',
|
|
31
|
+
evidence: evidenceOf(analysis.gate, analysis.productionFileCount, analysis.offenderCount),
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
export function consoleIsolationRule(scan) {
|
|
35
|
+
const analysis = scan.consoleIsolation;
|
|
36
|
+
return {
|
|
37
|
+
id: 'console-isolation',
|
|
38
|
+
family: 'console-isolation',
|
|
39
|
+
statement: FAMILY_STATEMENTS['console-isolation'],
|
|
40
|
+
mode: 'fast',
|
|
41
|
+
evidence: evidenceOf(analysis.gate, analysis.libraryFileCount, analysis.offenderCount),
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
export function importStyleRule(scan) {
|
|
45
|
+
const analysis = scan.deepRelative;
|
|
46
|
+
return {
|
|
47
|
+
id: 'import-style',
|
|
48
|
+
family: 'import-style',
|
|
49
|
+
statement: FAMILY_STATEMENTS['import-style'],
|
|
50
|
+
mode: 'fast',
|
|
51
|
+
evidence: evidenceOf(analysis.gate, analysis.relativeImporterCount, analysis.offenderCount),
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
export function publicApiRules(scan) {
|
|
55
|
+
return scan.publicApi.groups
|
|
56
|
+
.filter((group) => group.gate.status === 'AUTO')
|
|
57
|
+
.map((group) => ({
|
|
58
|
+
id: publicApiRuleName(group.dir),
|
|
59
|
+
family: 'public-api',
|
|
60
|
+
dir: group.dir,
|
|
61
|
+
statement: `import ${group.dir} through its public entry (barrel), not its internal files`,
|
|
62
|
+
mode: 'fast',
|
|
63
|
+
evidence: evidenceOf(group.gate, group.consumerCount, group.deepImporterCount),
|
|
64
|
+
}));
|
|
65
|
+
}
|
|
66
|
+
export function writeAdoptedRules(outDir, rules, archprintVersion) {
|
|
67
|
+
mkdirSync(outDir, { recursive: true });
|
|
68
|
+
const file = path.join(outDir, RULES_FILE);
|
|
69
|
+
const sorted = [...rules].sort((a, b) => a.id.localeCompare(b.id));
|
|
70
|
+
const content = { format: RULES_FORMAT, archprintVersion, rules: sorted };
|
|
71
|
+
writeFileSync(file, `${JSON.stringify(content, null, 2)}\n`);
|
|
72
|
+
return file;
|
|
73
|
+
}
|
|
74
|
+
export class InvalidRulesError extends Error {
|
|
75
|
+
}
|
|
76
|
+
const FAMILIES = new Set([
|
|
77
|
+
'forbidden-imports',
|
|
78
|
+
'public-api',
|
|
79
|
+
'test-isolation',
|
|
80
|
+
'console-isolation',
|
|
81
|
+
'import-style',
|
|
82
|
+
]);
|
|
83
|
+
const MAX_PATTERN_LENGTH = 200;
|
|
84
|
+
const PATTERN_FLAGS = /^[imsu]*$/;
|
|
85
|
+
function validateRule(rule, file) {
|
|
86
|
+
const invalid = (reason) => {
|
|
87
|
+
throw new InvalidRulesError(`${file}: ${reason}. Re-run archprint generate.`);
|
|
88
|
+
};
|
|
89
|
+
if (typeof rule !== 'object' || rule === null)
|
|
90
|
+
return invalid('a rule is not an object');
|
|
91
|
+
const candidate = rule;
|
|
92
|
+
if (typeof candidate.id !== 'string' || !FAMILIES.has(String(candidate.family))) {
|
|
93
|
+
return invalid('a rule has no valid id or family');
|
|
94
|
+
}
|
|
95
|
+
if (candidate.mode !== 'deep' && candidate.mode !== 'fast') {
|
|
96
|
+
return invalid(`rule ${candidate.id} has no valid resolution mode`);
|
|
97
|
+
}
|
|
98
|
+
if (candidate.family === 'forbidden-imports') {
|
|
99
|
+
const markers = candidate.forbidden;
|
|
100
|
+
if (!Array.isArray(markers) || !Array.isArray(candidate.roles)) {
|
|
101
|
+
return invalid(`rule ${candidate.id} has no roles or forbidden markers`);
|
|
102
|
+
}
|
|
103
|
+
for (const marker of markers) {
|
|
104
|
+
const { source, flags } = marker ?? {};
|
|
105
|
+
if (typeof source !== 'string' || source.length > MAX_PATTERN_LENGTH) {
|
|
106
|
+
return invalid(`rule ${candidate.id} has a missing or oversized pattern`);
|
|
107
|
+
}
|
|
108
|
+
if (typeof flags !== 'string' || !PATTERN_FLAGS.test(flags)) {
|
|
109
|
+
return invalid(`rule ${candidate.id} has unsupported pattern flags`);
|
|
110
|
+
}
|
|
111
|
+
try {
|
|
112
|
+
new RegExp(source, flags);
|
|
113
|
+
}
|
|
114
|
+
catch {
|
|
115
|
+
return invalid(`rule ${candidate.id} has an invalid pattern`);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
if (candidate.family === 'public-api' && typeof candidate.dir !== 'string') {
|
|
120
|
+
return invalid(`rule ${candidate.id} has no directory`);
|
|
121
|
+
}
|
|
122
|
+
return rule;
|
|
123
|
+
}
|
|
124
|
+
export function readAdoptedRules(outDir) {
|
|
125
|
+
const file = path.join(outDir, RULES_FILE);
|
|
126
|
+
if (!existsSync(file))
|
|
127
|
+
return null;
|
|
128
|
+
let parsed;
|
|
129
|
+
try {
|
|
130
|
+
parsed = JSON.parse(readFileSync(file, 'utf8'));
|
|
131
|
+
}
|
|
132
|
+
catch {
|
|
133
|
+
throw new InvalidRulesError(`${file} is not valid JSON. Re-run archprint generate.`);
|
|
134
|
+
}
|
|
135
|
+
if (parsed.format !== RULES_FORMAT || !Array.isArray(parsed.rules)) {
|
|
136
|
+
throw new InvalidRulesError(`${file} was written by a different archprint version. Re-run archprint generate.`);
|
|
137
|
+
}
|
|
138
|
+
return {
|
|
139
|
+
format: RULES_FORMAT,
|
|
140
|
+
archprintVersion: String(parsed.archprintVersion),
|
|
141
|
+
rules: parsed.rules.map((rule) => validateRule(rule, file)),
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
export function ruleDefinitionKey(rule) {
|
|
145
|
+
const common = [rule.family, rule.id, rule.mode];
|
|
146
|
+
switch (rule.family) {
|
|
147
|
+
case 'forbidden-imports':
|
|
148
|
+
return JSON.stringify([
|
|
149
|
+
...common,
|
|
150
|
+
[...rule.roles].sort(),
|
|
151
|
+
rule.forbidden.map((marker) => `${marker.source}/${marker.flags}`).sort(),
|
|
152
|
+
]);
|
|
153
|
+
case 'public-api':
|
|
154
|
+
return JSON.stringify([...common, rule.dir]);
|
|
155
|
+
default:
|
|
156
|
+
return JSON.stringify(common);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
//# sourceMappingURL=adopted-rules.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adopted-rules.js","sourceRoot":"","sources":["../../src/cli/adopted-rules.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAGlC,OAAO,EAAE,iBAAiB,EAAE,MAAM,qCAAqC,CAAC;AACxE,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAGzD,MAAM,CAAC,MAAM,UAAU,GAAG,YAAY,CAAC;AACvC,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,CAAC;AAwC9B,MAAM,UAAU,GAAG,CAAC,IAAgB,EAAE,KAAa,EAAE,SAAiB,EAAoB,EAAE,CAAC,CAAC;IAC5F,UAAU,EAAE,KAAK,GAAG,SAAS;IAC7B,KAAK;IACL,KAAK,EAAE,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,KAAK;CACxC,CAAC,CAAC;AAEH,MAAM,UAAU,mBAAmB,CAAC,OAAuB,EAAE,IAAoB;IAC/E,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;IACnC,OAAO;QACL,EAAE,EAAE,MAAM,CAAC,EAAE;QACb,MAAM,EAAE,mBAAmB;QAC3B,SAAS,EAAE,MAAM,CAAC,WAAW;QAC7B,IAAI;QACJ,KAAK,EAAE,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC;QACxB,SAAS,EAAE,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;QAC7F,QAAQ,EAAE,UAAU,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,KAAK,CAAC,aAAa,EAAE,MAAM,CAAC,KAAK,CAAC,kBAAkB,CAAC;KAC/F,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,IAAgB;IAChD,MAAM,QAAQ,GAAG,IAAI,CAAC,aAAa,CAAC;IACpC,OAAO;QACL,EAAE,EAAE,gBAAgB;QACpB,MAAM,EAAE,gBAAgB;QACxB,SAAS,EAAE,iBAAiB,CAAC,gBAAgB,CAAC;QAC9C,IAAI,EAAE,MAAM;QACZ,QAAQ,EAAE,UAAU,CAAC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,mBAAmB,EAAE,QAAQ,CAAC,aAAa,CAAC;KAC1F,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,IAAgB;IACnD,MAAM,QAAQ,GAAG,IAAI,CAAC,gBAAgB,CAAC;IACvC,OAAO;QACL,EAAE,EAAE,mBAAmB;QACvB,MAAM,EAAE,mBAAmB;QAC3B,SAAS,EAAE,iBAAiB,CAAC,mBAAmB,CAAC;QACjD,IAAI,EAAE,MAAM;QACZ,QAAQ,EAAE,UAAU,CAAC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,gBAAgB,EAAE,QAAQ,CAAC,aAAa,CAAC;KACvF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,IAAgB;IAC9C,MAAM,QAAQ,GAAG,IAAI,CAAC,YAAY,CAAC;IACnC,OAAO;QACL,EAAE,EAAE,cAAc;QAClB,MAAM,EAAE,cAAc;QACtB,SAAS,EAAE,iBAAiB,CAAC,cAAc,CAAC;QAC5C,IAAI,EAAE,MAAM;QACZ,QAAQ,EAAE,UAAU,CAAC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,qBAAqB,EAAE,QAAQ,CAAC,aAAa,CAAC;KAC5F,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,IAAgB;IAC7C,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM;SACzB,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,KAAK,MAAM,CAAC;SAC/C,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QACf,EAAE,EAAE,iBAAiB,CAAC,KAAK,CAAC,GAAG,CAAC;QAChC,MAAM,EAAE,YAAY;QACpB,GAAG,EAAE,KAAK,CAAC,GAAG;QACd,SAAS,EAAE,UAAU,KAAK,CAAC,GAAG,4DAA4D;QAC1F,IAAI,EAAE,MAAM;QACZ,QAAQ,EAAE,UAAU,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,aAAa,EAAE,KAAK,CAAC,iBAAiB,CAAC;KAC/E,CAAC,CAAC,CAAC;AACR,CAAC;AAED,MAAM,UAAU,iBAAiB,CAC/B,MAAc,EACd,KAA6B,EAC7B,gBAAwB;IAExB,SAAS,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACvC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IAC3C,MAAM,MAAM,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACnE,MAAM,OAAO,GAAiB,EAAE,MAAM,EAAE,YAAY,EAAE,gBAAgB,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;IACxF,aAAa,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;IAC7D,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,OAAO,iBAAkB,SAAQ,KAAK;CAAG;AAE/C,MAAM,QAAQ,GAAwB,IAAI,GAAG,CAAC;IAC5C,mBAAmB;IACnB,YAAY;IACZ,gBAAgB;IAChB,mBAAmB;IACnB,cAAc;CACf,CAAC,CAAC;AACH,MAAM,kBAAkB,GAAG,GAAG,CAAC;AAC/B,MAAM,aAAa,GAAG,WAAW,CAAC;AAElC,SAAS,YAAY,CAAC,IAAa,EAAE,IAAY;IAC/C,MAAM,OAAO,GAAG,CAAC,MAAc,EAAS,EAAE;QACxC,MAAM,IAAI,iBAAiB,CAAC,GAAG,IAAI,KAAK,MAAM,8BAA8B,CAAC,CAAC;IAChF,CAAC,CAAC;IACF,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI;QAAE,OAAO,OAAO,CAAC,yBAAyB,CAAC,CAAC;IACzF,MAAM,SAAS,GAAG,IAOjB,CAAC;IACF,IAAI,OAAO,SAAS,CAAC,EAAE,KAAK,QAAQ,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC;QAChF,OAAO,OAAO,CAAC,kCAAkC,CAAC,CAAC;IACrD,CAAC;IACD,IAAI,SAAS,CAAC,IAAI,KAAK,MAAM,IAAI,SAAS,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;QAC3D,OAAO,OAAO,CAAC,QAAQ,SAAS,CAAC,EAAE,+BAA+B,CAAC,CAAC;IACtE,CAAC;IACD,IAAI,SAAS,CAAC,MAAM,KAAK,mBAAmB,EAAE,CAAC;QAC7C,MAAM,OAAO,GAAG,SAAS,CAAC,SAAS,CAAC;QACpC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC;YAC/D,OAAO,OAAO,CAAC,QAAQ,SAAS,CAAC,EAAE,oCAAoC,CAAC,CAAC;QAC3E,CAAC;QACD,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;YAC7B,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,IAAI,EAAE,CAAC;YACvC,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,CAAC,MAAM,GAAG,kBAAkB,EAAE,CAAC;gBACrE,OAAO,OAAO,CAAC,QAAQ,SAAS,CAAC,EAAE,qCAAqC,CAAC,CAAC;YAC5E,CAAC;YACD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC5D,OAAO,OAAO,CAAC,QAAQ,SAAS,CAAC,EAAE,gCAAgC,CAAC,CAAC;YACvE,CAAC;YACD,IAAI,CAAC;gBACH,IAAI,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;YAC5B,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,OAAO,CAAC,QAAQ,SAAS,CAAC,EAAE,yBAAyB,CAAC,CAAC;YAChE,CAAC;QACH,CAAC;IACH,CAAC;IACD,IAAI,SAAS,CAAC,MAAM,KAAK,YAAY,IAAI,OAAO,SAAS,CAAC,GAAG,KAAK,QAAQ,EAAE,CAAC;QAC3E,OAAO,OAAO,CAAC,QAAQ,SAAS,CAAC,EAAE,mBAAmB,CAAC,CAAC;IAC1D,CAAC;IACD,OAAO,IAAmB,CAAC;AAC7B,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,MAAc;IAC7C,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IAC3C,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IACnC,IAAI,MAA6B,CAAC;IAClC,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAA0B,CAAC;IAC3E,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,iBAAiB,CAAC,GAAG,IAAI,gDAAgD,CAAC,CAAC;IACvF,CAAC;IACD,IAAI,MAAM,CAAC,MAAM,KAAK,YAAY,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;QACnE,MAAM,IAAI,iBAAiB,CACzB,GAAG,IAAI,2EAA2E,CACnF,CAAC;IACJ,CAAC;IACD,OAAO;QACL,MAAM,EAAE,YAAY;QACpB,gBAAgB,EAAE,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC;QACjD,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;KAC5D,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,IAAiB;IACjD,MAAM,MAAM,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;IACjD,QAAQ,IAAI,CAAC,MAAM,EAAE,CAAC;QACpB,KAAK,mBAAmB;YACtB,OAAO,IAAI,CAAC,SAAS,CAAC;gBACpB,GAAG,MAAM;gBACT,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE;gBACtB,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,IAAI,EAAE;aAC1E,CAAC,CAAC;QACL,KAAK,YAAY;YACf,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,GAAG,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QAC/C;YACE,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;IAClC,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type AdoptedRule } from './adopted-rules.js';
|
|
2
|
+
import type { Finding } from './check-evaluate.js';
|
|
3
|
+
export type RuleChange = 'new' | 'changed';
|
|
4
|
+
export interface RulePartition {
|
|
5
|
+
comparable: AdoptedRule[];
|
|
6
|
+
adoptedInChange: {
|
|
7
|
+
rule: AdoptedRule;
|
|
8
|
+
change: RuleChange;
|
|
9
|
+
}[];
|
|
10
|
+
removedInChange: AdoptedRule[];
|
|
11
|
+
}
|
|
12
|
+
export declare function partitionRules(head: readonly AdoptedRule[], base: readonly AdoptedRule[] | null): RulePartition;
|
|
13
|
+
export declare function renameFinding(finding: Finding, renames: ReadonlyMap<string, string>): Finding;
|
|
14
|
+
export interface FindingDiff {
|
|
15
|
+
introduced: Finding[];
|
|
16
|
+
fixed: Finding[];
|
|
17
|
+
}
|
|
18
|
+
export declare function diffFindings(base: readonly Finding[], head: readonly Finding[], renames: ReadonlyMap<string, string>): FindingDiff;
|
|
19
|
+
//# sourceMappingURL=check-diff.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check-diff.d.ts","sourceRoot":"","sources":["../../src/cli/check-diff.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqB,KAAK,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACzE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAEnD,MAAM,MAAM,UAAU,GAAG,KAAK,GAAG,SAAS,CAAC;AAE3C,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,WAAW,EAAE,CAAC;IAC1B,eAAe,EAAE;QAAE,IAAI,EAAE,WAAW,CAAC;QAAC,MAAM,EAAE,UAAU,CAAA;KAAE,EAAE,CAAC;IAC7D,eAAe,EAAE,WAAW,EAAE,CAAC;CAChC;AAED,wBAAgB,cAAc,CAC5B,IAAI,EAAE,SAAS,WAAW,EAAE,EAC5B,IAAI,EAAE,SAAS,WAAW,EAAE,GAAG,IAAI,GAClC,aAAa,CAgBf;AAKD,wBAAgB,aAAa,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAS7F;AAED,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,OAAO,EAAE,CAAC;IACtB,KAAK,EAAE,OAAO,EAAE,CAAC;CAClB;AAED,wBAAgB,YAAY,CAC1B,IAAI,EAAE,SAAS,OAAO,EAAE,EACxB,IAAI,EAAE,SAAS,OAAO,EAAE,EACxB,OAAO,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,GACnC,WAAW,CASb"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { ruleDefinitionKey } from './adopted-rules.js';
|
|
2
|
+
export function partitionRules(head, base) {
|
|
3
|
+
const baseById = new Map((base ?? []).map((rule) => [rule.id, rule]));
|
|
4
|
+
const headIds = new Set(head.map((rule) => rule.id));
|
|
5
|
+
const partition = {
|
|
6
|
+
comparable: [],
|
|
7
|
+
adoptedInChange: [],
|
|
8
|
+
removedInChange: (base ?? []).filter((rule) => !headIds.has(rule.id)),
|
|
9
|
+
};
|
|
10
|
+
for (const rule of head) {
|
|
11
|
+
const prior = baseById.get(rule.id);
|
|
12
|
+
if (prior === undefined)
|
|
13
|
+
partition.adoptedInChange.push({ rule, change: 'new' });
|
|
14
|
+
else if (ruleDefinitionKey(prior) !== ruleDefinitionKey(rule))
|
|
15
|
+
partition.adoptedInChange.push({ rule, change: 'changed' });
|
|
16
|
+
else
|
|
17
|
+
partition.comparable.push(rule);
|
|
18
|
+
}
|
|
19
|
+
return partition;
|
|
20
|
+
}
|
|
21
|
+
const identity = (finding) => [finding.ruleId, finding.file, finding.subject].join('\u0000');
|
|
22
|
+
export function renameFinding(finding, renames) {
|
|
23
|
+
return {
|
|
24
|
+
...finding,
|
|
25
|
+
file: renames.get(finding.file) ?? finding.file,
|
|
26
|
+
subject: finding.kind === 'target'
|
|
27
|
+
? (renames.get(finding.subject) ?? finding.subject)
|
|
28
|
+
: finding.subject,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
export function diffFindings(base, head, renames) {
|
|
32
|
+
const renamedBase = base.map((finding) => renameFinding(finding, renames));
|
|
33
|
+
const baseKeys = new Set(renamedBase.map(identity));
|
|
34
|
+
const headKeys = new Set(head.map(identity));
|
|
35
|
+
const byIdentity = (a, b) => identity(a).localeCompare(identity(b));
|
|
36
|
+
return {
|
|
37
|
+
introduced: head.filter((finding) => !baseKeys.has(identity(finding))).sort(byIdentity),
|
|
38
|
+
fixed: renamedBase.filter((finding) => !headKeys.has(identity(finding))).sort(byIdentity),
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=check-diff.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check-diff.js","sourceRoot":"","sources":["../../src/cli/check-diff.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAoB,MAAM,oBAAoB,CAAC;AAWzE,MAAM,UAAU,cAAc,CAC5B,IAA4B,EAC5B,IAAmC;IAEnC,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC;IACtE,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;IACrD,MAAM,SAAS,GAAkB;QAC/B,UAAU,EAAE,EAAE;QACd,eAAe,EAAE,EAAE;QACnB,eAAe,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;KACtE,CAAC;IACF,KAAK,MAAM,IAAI,IAAI,IAAI,EAAE,CAAC;QACxB,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACpC,IAAI,KAAK,KAAK,SAAS;YAAE,SAAS,CAAC,eAAe,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;aAC5E,IAAI,iBAAiB,CAAC,KAAK,CAAC,KAAK,iBAAiB,CAAC,IAAI,CAAC;YAC3D,SAAS,CAAC,eAAe,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC;;YACzD,SAAS,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACvC,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,MAAM,QAAQ,GAAG,CAAC,OAAgB,EAAU,EAAE,CAC5C,CAAC,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;AAEjE,MAAM,UAAU,aAAa,CAAC,OAAgB,EAAE,OAAoC;IAClF,OAAO;QACL,GAAG,OAAO;QACV,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,OAAO,CAAC,IAAI;QAC/C,OAAO,EACL,OAAO,CAAC,IAAI,KAAK,QAAQ;YACvB,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,OAAO,CAAC,OAAO,CAAC;YACnD,CAAC,CAAC,OAAO,CAAC,OAAO;KACtB,CAAC;AACJ,CAAC;AAOD,MAAM,UAAU,YAAY,CAC1B,IAAwB,EACxB,IAAwB,EACxB,OAAoC;IAEpC,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,aAAa,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;IAC3E,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC;IACpD,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC7C,MAAM,UAAU,GAAG,CAAC,CAAU,EAAE,CAAU,EAAU,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9F,OAAO;QACL,UAAU,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC;QACvF,KAAK,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC;KAC1F,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { AdoptedRule } from './adopted-rules.js';
|
|
2
|
+
export type SubjectKind = 'specifier' | 'target' | 'file';
|
|
3
|
+
export interface Finding {
|
|
4
|
+
ruleId: string;
|
|
5
|
+
file: string;
|
|
6
|
+
subject: string;
|
|
7
|
+
kind: SubjectKind;
|
|
8
|
+
}
|
|
9
|
+
export declare function evaluateRules(appDir: string, rules: readonly AdoptedRule[]): Finding[];
|
|
10
|
+
//# sourceMappingURL=check-evaluate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check-evaluate.d.ts","sourceRoot":"","sources":["../../src/cli/check-evaluate.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,WAAW,EAAuC,MAAM,oBAAoB,CAAC;AAE3F,MAAM,MAAM,WAAW,GAAG,WAAW,GAAG,QAAQ,GAAG,MAAM,CAAC;AAE1D,MAAM,WAAW,OAAO;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,WAAW,CAAC;CACnB;AAiCD,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,WAAW,EAAE,GAAG,OAAO,EAAE,CAkDtF"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { detectConsoleIsolation } from '../detector/console-isolation-detector.js';
|
|
2
|
+
import { detectDeepRelativeImports } from '../detector/deep-relative-detector.js';
|
|
3
|
+
import { detectForbiddenImports } from '../detector/pattern-detector.js';
|
|
4
|
+
import { detectPublicApiBoundaries } from '../detector/public-api-detector.js';
|
|
5
|
+
import { detectTestIsolation } from '../detector/test-isolation-detector.js';
|
|
6
|
+
const toPatternConfig = (rule) => ({
|
|
7
|
+
id: rule.id,
|
|
8
|
+
name: rule.id,
|
|
9
|
+
description: rule.statement,
|
|
10
|
+
roles: rule.roles,
|
|
11
|
+
forbidden: rule.forbidden.map((marker) => new RegExp(marker.source, marker.flags)),
|
|
12
|
+
});
|
|
13
|
+
function forbiddenImportFindings(appDir, rules) {
|
|
14
|
+
const findings = [];
|
|
15
|
+
const modes = ['deep', 'fast'];
|
|
16
|
+
for (const mode of modes) {
|
|
17
|
+
const group = rules.filter((rule) => rule.mode === mode);
|
|
18
|
+
if (group.length === 0)
|
|
19
|
+
continue;
|
|
20
|
+
const results = detectForbiddenImports(appDir, group.map(toPatternConfig), {
|
|
21
|
+
resolve: mode === 'deep',
|
|
22
|
+
});
|
|
23
|
+
results.forEach((result, index) => {
|
|
24
|
+
for (const violation of result.violations) {
|
|
25
|
+
findings.push({
|
|
26
|
+
ruleId: group[index].id,
|
|
27
|
+
file: violation.file,
|
|
28
|
+
subject: violation.specifier,
|
|
29
|
+
kind: 'specifier',
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
return findings;
|
|
35
|
+
}
|
|
36
|
+
export function evaluateRules(appDir, rules) {
|
|
37
|
+
const findings = forbiddenImportFindings(appDir, rules.filter((rule) => rule.family === 'forbidden-imports'));
|
|
38
|
+
const byFamily = (family) => rules.filter((rule) => rule.family === family);
|
|
39
|
+
for (const rule of byFamily('test-isolation')) {
|
|
40
|
+
for (const violation of detectTestIsolation(appDir).violations) {
|
|
41
|
+
findings.push({
|
|
42
|
+
ruleId: rule.id,
|
|
43
|
+
file: violation.file,
|
|
44
|
+
subject: violation.target,
|
|
45
|
+
kind: 'target',
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
for (const rule of byFamily('console-isolation')) {
|
|
50
|
+
for (const violation of detectConsoleIsolation(appDir).violations) {
|
|
51
|
+
findings.push({ ruleId: rule.id, file: violation.file, subject: '', kind: 'file' });
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
for (const rule of byFamily('import-style')) {
|
|
55
|
+
for (const violation of detectDeepRelativeImports(appDir).violations) {
|
|
56
|
+
findings.push({
|
|
57
|
+
ruleId: rule.id,
|
|
58
|
+
file: violation.file,
|
|
59
|
+
subject: violation.specifier,
|
|
60
|
+
kind: 'specifier',
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
const publicApi = byFamily('public-api');
|
|
65
|
+
if (publicApi.length > 0) {
|
|
66
|
+
const groups = detectPublicApiBoundaries(appDir).groups;
|
|
67
|
+
for (const rule of publicApi) {
|
|
68
|
+
if (rule.family !== 'public-api')
|
|
69
|
+
continue;
|
|
70
|
+
const group = groups.find((candidate) => candidate.dir === rule.dir);
|
|
71
|
+
for (const violation of group?.violations ?? []) {
|
|
72
|
+
findings.push({
|
|
73
|
+
ruleId: rule.id,
|
|
74
|
+
file: violation.file,
|
|
75
|
+
subject: violation.target,
|
|
76
|
+
kind: 'target',
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return findings;
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=check-evaluate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check-evaluate.js","sourceRoot":"","sources":["../../src/cli/check-evaluate.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export declare class CheckSetupError extends Error {
|
|
2
|
+
}
|
|
3
|
+
export declare const repoRoot: (cwd: string) => string;
|
|
4
|
+
export declare function defaultBase(root: string): string;
|
|
5
|
+
export declare function mergeBase(root: string, base: string): string;
|
|
6
|
+
export declare function renamedPaths(root: string, commit: string): Map<string, string>;
|
|
7
|
+
export interface BaseTree {
|
|
8
|
+
root: string;
|
|
9
|
+
dispose: () => void;
|
|
10
|
+
}
|
|
11
|
+
export declare function checkoutBase(root: string, commit: string, appRelative: string): BaseTree;
|
|
12
|
+
//# sourceMappingURL=check-git.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check-git.d.ts","sourceRoot":"","sources":["../../src/cli/check-git.ts"],"names":[],"mappings":"AAMA,qBAAa,eAAgB,SAAQ,KAAK;CAAG;AAgB7C,eAAO,MAAM,QAAQ,GAAI,KAAK,MAAM,KAAG,MAA2D,CAAC;AAEnG,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAQhD;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAQ5D;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAc9E;AAED,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAgBD,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,QAAQ,CAoBxF"}
|