oxlint-architecture-rules 0.1.0-beta.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/LICENSE +21 -0
- package/build/dts/adapters/cli/main.d.ts +3 -0
- package/build/dts/adapters/cli/main.d.ts.map +1 -0
- package/build/dts/adapters/cli/run.d.ts +19 -0
- package/build/dts/adapters/cli/run.d.ts.map +1 -0
- package/build/dts/adapters/cli/source-facts.d.ts +9 -0
- package/build/dts/adapters/cli/source-facts.d.ts.map +1 -0
- package/build/dts/adapters/cli/source-files.d.ts +2 -0
- package/build/dts/adapters/cli/source-files.d.ts.map +1 -0
- package/build/dts/adapters/oxlint/config-loader.d.ts +23 -0
- package/build/dts/adapters/oxlint/config-loader.d.ts.map +1 -0
- package/build/dts/adapters/oxlint/exports-rule.d.ts +4 -0
- package/build/dts/adapters/oxlint/exports-rule.d.ts.map +1 -0
- package/build/dts/adapters/oxlint/imports-rule.d.ts +4 -0
- package/build/dts/adapters/oxlint/imports-rule.d.ts.map +1 -0
- package/build/dts/adapters/oxlint/members-rule.d.ts +4 -0
- package/build/dts/adapters/oxlint/members-rule.d.ts.map +1 -0
- package/build/dts/adapters/oxlint/oxlint-api.d.ts +19 -0
- package/build/dts/adapters/oxlint/oxlint-api.d.ts.map +1 -0
- package/build/dts/adapters/oxlint/plugin.d.ts +15 -0
- package/build/dts/adapters/oxlint/plugin.d.ts.map +1 -0
- package/build/dts/adapters/oxlint/structure-rule.d.ts +4 -0
- package/build/dts/adapters/oxlint/structure-rule.d.ts.map +1 -0
- package/build/dts/core/baseline.d.ts +16 -0
- package/build/dts/core/baseline.d.ts.map +1 -0
- package/build/dts/core/exports.d.ts +39 -0
- package/build/dts/core/exports.d.ts.map +1 -0
- package/build/dts/core/imports.d.ts +27 -0
- package/build/dts/core/imports.d.ts.map +1 -0
- package/build/dts/core/members.d.ts +28 -0
- package/build/dts/core/members.d.ts.map +1 -0
- package/build/dts/core/patterns.d.ts +19 -0
- package/build/dts/core/patterns.d.ts.map +1 -0
- package/build/dts/core/structure.d.ts +48 -0
- package/build/dts/core/structure.d.ts.map +1 -0
- package/build/dts/domain/architecture-config.d.ts +177 -0
- package/build/dts/domain/architecture-config.d.ts.map +1 -0
- package/build/dts/domain/architecture-error.d.ts +27 -0
- package/build/dts/domain/architecture-error.d.ts.map +1 -0
- package/build/dts/domain/violation.d.ts +11 -0
- package/build/dts/domain/violation.d.ts.map +1 -0
- package/build/dts/index.d.ts +10 -0
- package/build/dts/index.d.ts.map +1 -0
- package/build/dts/infrastructure/file-system-fake.d.ts +3 -0
- package/build/dts/infrastructure/file-system-fake.d.ts.map +1 -0
- package/build/dts/infrastructure/file-system-live.d.ts +3 -0
- package/build/dts/infrastructure/file-system-live.d.ts.map +1 -0
- package/build/dts/infrastructure/module-resolver-fake.d.ts +3 -0
- package/build/dts/infrastructure/module-resolver-fake.d.ts.map +1 -0
- package/build/dts/infrastructure/module-resolver-live.d.ts +4 -0
- package/build/dts/infrastructure/module-resolver-live.d.ts.map +1 -0
- package/build/dts/manifest/compile.d.ts +16 -0
- package/build/dts/manifest/compile.d.ts.map +1 -0
- package/build/dts/manifest/glob.d.ts +14 -0
- package/build/dts/manifest/glob.d.ts.map +1 -0
- package/build/dts/manifest/manifest.d.ts +96 -0
- package/build/dts/manifest/manifest.d.ts.map +1 -0
- package/build/dts/ports/file-system.d.ts +4 -0
- package/build/dts/ports/file-system.d.ts.map +1 -0
- package/build/dts/ports/module-resolver.d.ts +11 -0
- package/build/dts/ports/module-resolver.d.ts.map +1 -0
- package/build/esm/adapters/cli/main.js +17 -0
- package/build/esm/adapters/cli/main.js.map +1 -0
- package/build/esm/adapters/cli/run.js +188 -0
- package/build/esm/adapters/cli/run.js.map +1 -0
- package/build/esm/adapters/cli/source-facts.js +117 -0
- package/build/esm/adapters/cli/source-facts.js.map +1 -0
- package/build/esm/adapters/cli/source-files.js +40 -0
- package/build/esm/adapters/cli/source-files.js.map +1 -0
- package/build/esm/adapters/oxlint/config-loader.js +81 -0
- package/build/esm/adapters/oxlint/config-loader.js.map +1 -0
- package/build/esm/adapters/oxlint/exports-rule.js +104 -0
- package/build/esm/adapters/oxlint/exports-rule.js.map +1 -0
- package/build/esm/adapters/oxlint/imports-rule.js +55 -0
- package/build/esm/adapters/oxlint/imports-rule.js.map +1 -0
- package/build/esm/adapters/oxlint/members-rule.js +75 -0
- package/build/esm/adapters/oxlint/members-rule.js.map +1 -0
- package/build/esm/adapters/oxlint/oxlint-api.js +7 -0
- package/build/esm/adapters/oxlint/oxlint-api.js.map +1 -0
- package/build/esm/adapters/oxlint/plugin.js +23 -0
- package/build/esm/adapters/oxlint/plugin.js.map +1 -0
- package/build/esm/adapters/oxlint/structure-rule.js +37 -0
- package/build/esm/adapters/oxlint/structure-rule.js.map +1 -0
- package/build/esm/core/baseline.js +30 -0
- package/build/esm/core/baseline.js.map +1 -0
- package/build/esm/core/exports.js +96 -0
- package/build/esm/core/exports.js.map +1 -0
- package/build/esm/core/imports.js +85 -0
- package/build/esm/core/imports.js.map +1 -0
- package/build/esm/core/members.js +84 -0
- package/build/esm/core/members.js.map +1 -0
- package/build/esm/core/patterns.js +78 -0
- package/build/esm/core/patterns.js.map +1 -0
- package/build/esm/core/structure.js +256 -0
- package/build/esm/core/structure.js.map +1 -0
- package/build/esm/domain/architecture-config.js +172 -0
- package/build/esm/domain/architecture-config.js.map +1 -0
- package/build/esm/domain/architecture-error.js +29 -0
- package/build/esm/domain/architecture-error.js.map +1 -0
- package/build/esm/domain/violation.js +8 -0
- package/build/esm/domain/violation.js.map +1 -0
- package/build/esm/index.js +8 -0
- package/build/esm/index.js.map +1 -0
- package/build/esm/infrastructure/file-system-fake.js +5 -0
- package/build/esm/infrastructure/file-system-fake.js.map +1 -0
- package/build/esm/infrastructure/file-system-live.js +19 -0
- package/build/esm/infrastructure/file-system-live.js.map +1 -0
- package/build/esm/infrastructure/module-resolver-fake.js +23 -0
- package/build/esm/infrastructure/module-resolver-fake.js.map +1 -0
- package/build/esm/infrastructure/module-resolver-live.js +71 -0
- package/build/esm/infrastructure/module-resolver-live.js.map +1 -0
- package/build/esm/manifest/compile.js +503 -0
- package/build/esm/manifest/compile.js.map +1 -0
- package/build/esm/manifest/glob.js +77 -0
- package/build/esm/manifest/glob.js.map +1 -0
- package/build/esm/manifest/manifest.js +120 -0
- package/build/esm/manifest/manifest.js.map +1 -0
- package/build/esm/ports/file-system.js +2 -0
- package/build/esm/ports/file-system.js.map +1 -0
- package/build/esm/ports/module-resolver.js +2 -0
- package/build/esm/ports/module-resolver.js.map +1 -0
- package/package.json +73 -0
- package/src/adapters/cli/main.ts +20 -0
- package/src/adapters/cli/run.ts +270 -0
- package/src/adapters/cli/source-facts.ts +137 -0
- package/src/adapters/cli/source-files.ts +42 -0
- package/src/adapters/oxlint/config-loader.ts +136 -0
- package/src/adapters/oxlint/exports-rule.ts +144 -0
- package/src/adapters/oxlint/imports-rule.ts +67 -0
- package/src/adapters/oxlint/members-rule.ts +114 -0
- package/src/adapters/oxlint/oxlint-api.ts +25 -0
- package/src/adapters/oxlint/plugin.ts +35 -0
- package/src/adapters/oxlint/structure-rule.ts +39 -0
- package/src/core/baseline.ts +62 -0
- package/src/core/exports.ts +164 -0
- package/src/core/imports.ts +138 -0
- package/src/core/members.ts +131 -0
- package/src/core/patterns.ts +122 -0
- package/src/core/structure.ts +348 -0
- package/src/domain/architecture-config.ts +206 -0
- package/src/domain/architecture-error.ts +43 -0
- package/src/domain/violation.ts +24 -0
- package/src/index.ts +28 -0
- package/src/infrastructure/file-system-fake.ts +6 -0
- package/src/infrastructure/file-system-live.ts +20 -0
- package/src/infrastructure/module-resolver-fake.ts +29 -0
- package/src/infrastructure/module-resolver-live.ts +100 -0
- package/src/manifest/compile.ts +736 -0
- package/src/manifest/glob.ts +108 -0
- package/src/manifest/manifest.ts +178 -0
- package/src/ports/file-system.ts +5 -0
- package/src/ports/module-resolver.ts +23 -0
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import * as Result from "effect/Result";
|
|
2
|
+
import { compilePatterns, firstFromMatch, kindOfPath, sourcesOf, targetAllowed, validateTargetPatterns, } from "./patterns.js";
|
|
3
|
+
export const compileImportRule = (rule) => {
|
|
4
|
+
const from = compilePatterns(rule.name, "from", rule.from);
|
|
5
|
+
if (Result.isFailure(from))
|
|
6
|
+
return Result.fail(from.failure);
|
|
7
|
+
const fromNot = compilePatterns(rule.name, "fromNot", rule.fromNot);
|
|
8
|
+
if (Result.isFailure(fromNot))
|
|
9
|
+
return Result.fail(fromNot.failure);
|
|
10
|
+
const targets = validateTargetPatterns(rule.name, [
|
|
11
|
+
["to", rule.to],
|
|
12
|
+
["toNot", rule.toNot],
|
|
13
|
+
]);
|
|
14
|
+
if (Result.isFailure(targets))
|
|
15
|
+
return Result.fail(targets.failure);
|
|
16
|
+
return Result.succeed({
|
|
17
|
+
name: rule.name,
|
|
18
|
+
message: rule.message,
|
|
19
|
+
probe: rule.probe,
|
|
20
|
+
from: from.success,
|
|
21
|
+
fromNot: fromNot.success,
|
|
22
|
+
to: sourcesOf(rule.to),
|
|
23
|
+
toNot: sourcesOf(rule.toNot),
|
|
24
|
+
dependencyKind: rule.dependencyKind ?? null,
|
|
25
|
+
});
|
|
26
|
+
};
|
|
27
|
+
export const compileImportRules = (rules) => {
|
|
28
|
+
const compiled = [];
|
|
29
|
+
for (const rule of rules) {
|
|
30
|
+
const one = compileImportRule(rule);
|
|
31
|
+
if (Result.isFailure(one))
|
|
32
|
+
return Result.fail(one.failure);
|
|
33
|
+
compiled.push(one.success);
|
|
34
|
+
}
|
|
35
|
+
return Result.succeed(compiled);
|
|
36
|
+
};
|
|
37
|
+
// Returns the rules whose `from` side selects this file. A file no rule selects
|
|
38
|
+
// never needs its imports resolved, which is what keeps resolution off the hot
|
|
39
|
+
// path for the bulk of the repo.
|
|
40
|
+
export const rulesSelecting = (rules, importer) => {
|
|
41
|
+
const selected = [];
|
|
42
|
+
for (const rule of rules) {
|
|
43
|
+
const captures = firstFromMatch(rule, importer);
|
|
44
|
+
if (captures !== null)
|
|
45
|
+
selected.push([rule, captures]);
|
|
46
|
+
}
|
|
47
|
+
return selected;
|
|
48
|
+
};
|
|
49
|
+
export const evaluateSelectedEdge = (selected, resolver, edge) => {
|
|
50
|
+
if (selected.length === 0)
|
|
51
|
+
return Result.succeed([]);
|
|
52
|
+
const resolved = resolver.resolve(edge.importer, edge.specifier);
|
|
53
|
+
if (Result.isFailure(resolved))
|
|
54
|
+
return Result.fail(resolved.failure);
|
|
55
|
+
const target = resolved.success;
|
|
56
|
+
const violations = [];
|
|
57
|
+
for (const [rule, captures] of selected) {
|
|
58
|
+
if (rule.dependencyKind !== null && rule.dependencyKind !== target.kind)
|
|
59
|
+
continue;
|
|
60
|
+
if (targetAllowed(rule, captures, target.path)) {
|
|
61
|
+
violations.push({
|
|
62
|
+
kind: "import",
|
|
63
|
+
ruleName: rule.name,
|
|
64
|
+
message: rule.message,
|
|
65
|
+
file: edge.importer,
|
|
66
|
+
subject: target.path,
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return Result.succeed(violations);
|
|
71
|
+
};
|
|
72
|
+
export const evaluateImportEdge = (rules, resolver, edge) => evaluateSelectedEdge(rulesSelecting(rules, edge.importer), resolver, edge);
|
|
73
|
+
// Every rule must report its own probe. A rule that does not is enforcing
|
|
74
|
+
// nothing while still looking configured and still passing a clean lint run —
|
|
75
|
+
// the one failure mode a linter cannot surface on its own.
|
|
76
|
+
export const rulesFailingTheirProbe = (rules) => rules.filter((rule) => {
|
|
77
|
+
const captures = firstFromMatch(rule, rule.probe.from);
|
|
78
|
+
if (captures === null)
|
|
79
|
+
return true;
|
|
80
|
+
if (rule.dependencyKind !== null && rule.dependencyKind !== kindOfPath(rule.probe.to)) {
|
|
81
|
+
return true;
|
|
82
|
+
}
|
|
83
|
+
return !targetAllowed(rule, captures, rule.probe.to);
|
|
84
|
+
});
|
|
85
|
+
//# sourceMappingURL=imports.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"imports.js","sourceRoot":"","sources":["../../../src/core/imports.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import * as Result from "effect/Result";
|
|
2
|
+
import { compilePatterns, firstFromMatch } from "./patterns.js";
|
|
3
|
+
export const compileMemberRule = (rule) => {
|
|
4
|
+
const fields = [
|
|
5
|
+
["from", rule.from],
|
|
6
|
+
["fromNot", rule.fromNot],
|
|
7
|
+
["in", rule.in],
|
|
8
|
+
["match", rule.match],
|
|
9
|
+
["matchNot", rule.matchNot],
|
|
10
|
+
["allow", rule.allow],
|
|
11
|
+
];
|
|
12
|
+
const compiled = [];
|
|
13
|
+
for (const [field, patterns] of fields) {
|
|
14
|
+
const one = compilePatterns(rule.name, field, patterns);
|
|
15
|
+
if (Result.isFailure(one))
|
|
16
|
+
return Result.fail(one.failure);
|
|
17
|
+
compiled.push(one.success);
|
|
18
|
+
}
|
|
19
|
+
const [from, fromNot, inside, match, matchNot, allow] = compiled;
|
|
20
|
+
return Result.succeed({
|
|
21
|
+
name: rule.name,
|
|
22
|
+
message: rule.message,
|
|
23
|
+
probe: rule.probe,
|
|
24
|
+
subject: rule.subject,
|
|
25
|
+
from,
|
|
26
|
+
fromNot,
|
|
27
|
+
in: inside,
|
|
28
|
+
match,
|
|
29
|
+
matchNot,
|
|
30
|
+
allow,
|
|
31
|
+
});
|
|
32
|
+
};
|
|
33
|
+
export const compileMemberRules = (rules) => {
|
|
34
|
+
const compiled = [];
|
|
35
|
+
for (const rule of rules) {
|
|
36
|
+
const one = compileMemberRule(rule);
|
|
37
|
+
if (Result.isFailure(one))
|
|
38
|
+
return Result.fail(one.failure);
|
|
39
|
+
compiled.push(one.success);
|
|
40
|
+
}
|
|
41
|
+
return Result.succeed(compiled);
|
|
42
|
+
};
|
|
43
|
+
const anyMatches = (patterns, value) => patterns.some((pattern) => pattern.test(value));
|
|
44
|
+
export const memberRulesSelecting = (rules, file) => rules.filter((rule) => firstFromMatch(rule, file) !== null);
|
|
45
|
+
const governs = (rule, site) => {
|
|
46
|
+
if (rule.subject !== site.subject)
|
|
47
|
+
return false;
|
|
48
|
+
if (rule.in.length > 0 && (site.in === undefined || !anyMatches(rule.in, site.in)))
|
|
49
|
+
return false;
|
|
50
|
+
if (rule.match.length > 0 && !anyMatches(rule.match, site.name))
|
|
51
|
+
return false;
|
|
52
|
+
if (rule.matchNot.length > 0 && anyMatches(rule.matchNot, site.name))
|
|
53
|
+
return false;
|
|
54
|
+
return true;
|
|
55
|
+
};
|
|
56
|
+
export const evaluateMemberSite = (selected, site) => {
|
|
57
|
+
const violations = [];
|
|
58
|
+
for (const rule of selected) {
|
|
59
|
+
if (!governs(rule, site))
|
|
60
|
+
continue;
|
|
61
|
+
if (anyMatches(rule.allow, site.name))
|
|
62
|
+
continue;
|
|
63
|
+
violations.push({
|
|
64
|
+
kind: "member",
|
|
65
|
+
ruleName: rule.name,
|
|
66
|
+
message: rule.message,
|
|
67
|
+
file: site.file,
|
|
68
|
+
subject: site.name,
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
return violations;
|
|
72
|
+
};
|
|
73
|
+
export const memberRulesFailingTheirProbe = (rules) => rules.filter((rule) => {
|
|
74
|
+
const site = {
|
|
75
|
+
file: rule.probe.from,
|
|
76
|
+
subject: rule.subject,
|
|
77
|
+
name: rule.probe.name,
|
|
78
|
+
...(rule.probe.in === undefined ? {} : { in: rule.probe.in }),
|
|
79
|
+
};
|
|
80
|
+
if (firstFromMatch(rule, site.file) === null)
|
|
81
|
+
return true;
|
|
82
|
+
return evaluateMemberSite([rule], site).length === 0;
|
|
83
|
+
});
|
|
84
|
+
//# sourceMappingURL=members.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"members.js","sourceRoot":"","sources":["../../../src/core/members.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import * as Result from "effect/Result";
|
|
2
|
+
import { patternsOf } from "../domain/architecture-config.js";
|
|
3
|
+
import { PatternInvalid } from "../domain/architecture-error.js";
|
|
4
|
+
const BACKREFERENCE = /\$([1-9])/g;
|
|
5
|
+
// Validation-only stand-in so `new RegExp` sees a syntactically complete pattern
|
|
6
|
+
// where a backreference will later be spliced.
|
|
7
|
+
const withPlaceholderCaptures = (pattern) => pattern.replaceAll(BACKREFERENCE, "x");
|
|
8
|
+
const compilePattern = (ruleName, field, pattern) => {
|
|
9
|
+
try {
|
|
10
|
+
return Result.succeed(new RegExp(pattern));
|
|
11
|
+
}
|
|
12
|
+
catch (cause) {
|
|
13
|
+
return Result.fail(new PatternInvalid({ ruleName, field, pattern, detail: String(cause) }));
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
export const compilePatterns = (ruleName, field, patterns) => {
|
|
17
|
+
const sources = patterns === undefined ? [] : patternsOf(patterns);
|
|
18
|
+
const compiled = [];
|
|
19
|
+
for (const source of sources) {
|
|
20
|
+
const one = compilePattern(ruleName, field, source);
|
|
21
|
+
if (Result.isFailure(one))
|
|
22
|
+
return Result.fail(one.failure);
|
|
23
|
+
compiled.push(one.success);
|
|
24
|
+
}
|
|
25
|
+
return Result.succeed(compiled);
|
|
26
|
+
};
|
|
27
|
+
// Target patterns are compiled per edge (a `$1` is only known once the `from`
|
|
28
|
+
// side has matched), so they are validated separately at load. A typo in a
|
|
29
|
+
// `toNot` must fail the config, not lie dormant until some file happens to
|
|
30
|
+
// select the rule.
|
|
31
|
+
export const validateTargetPatterns = (ruleName, fields) => {
|
|
32
|
+
for (const [field, patterns] of fields) {
|
|
33
|
+
const validated = compilePatterns(ruleName, field, patterns === undefined ? undefined : patternsOf(patterns).map(withPlaceholderCaptures));
|
|
34
|
+
if (Result.isFailure(validated))
|
|
35
|
+
return Result.fail(validated.failure);
|
|
36
|
+
}
|
|
37
|
+
return Result.succeed(undefined);
|
|
38
|
+
};
|
|
39
|
+
export const sourcesOf = (patterns) => (patterns === undefined ? [] : [...patternsOf(patterns)]);
|
|
40
|
+
// A capture is one path segment from the importer, spliced into a target
|
|
41
|
+
// pattern as `$1`. It is data, not pattern syntax: a folder named `my.module`
|
|
42
|
+
// must match itself, not "my" plus any character plus "module".
|
|
43
|
+
const REGEX_METACHARACTER = /[.*+?^${}()|[\]\\]/g;
|
|
44
|
+
const substitute = (pattern, captures) => pattern.replaceAll(BACKREFERENCE, (whole, index) => {
|
|
45
|
+
const capture = captures[Number(index)];
|
|
46
|
+
return capture === undefined ? whole : capture.replace(REGEX_METACHARACTER, "\\$&");
|
|
47
|
+
});
|
|
48
|
+
const targetCache = new Map();
|
|
49
|
+
const compiledTarget = (pattern) => {
|
|
50
|
+
const cached = targetCache.get(pattern);
|
|
51
|
+
if (cached !== undefined)
|
|
52
|
+
return cached;
|
|
53
|
+
const compiled = new RegExp(pattern);
|
|
54
|
+
targetCache.set(pattern, compiled);
|
|
55
|
+
return compiled;
|
|
56
|
+
};
|
|
57
|
+
export const matchesAny = (patterns, captures, value) => patterns.some((pattern) => compiledTarget(substitute(pattern, captures)).test(value));
|
|
58
|
+
export const firstFromMatch = (rule, importer) => {
|
|
59
|
+
if (rule.fromNot.some((pattern) => pattern.test(importer)))
|
|
60
|
+
return null;
|
|
61
|
+
for (const pattern of rule.from) {
|
|
62
|
+
const captures = pattern.exec(importer);
|
|
63
|
+
if (captures !== null)
|
|
64
|
+
return captures;
|
|
65
|
+
}
|
|
66
|
+
return null;
|
|
67
|
+
};
|
|
68
|
+
// A probe states its target as a resolved path, so its dependency kind is read
|
|
69
|
+
// back off that path rather than restated in the config.
|
|
70
|
+
export const kindOfPath = (path) => path.startsWith("node:") ? "builtin" : path.includes("node_modules/") ? "external" : "local";
|
|
71
|
+
export const targetAllowed = (rule, captures, targetPath) => {
|
|
72
|
+
if (rule.to.length > 0 && !matchesAny(rule.to, captures, targetPath))
|
|
73
|
+
return false;
|
|
74
|
+
if (rule.toNot.length > 0 && matchesAny(rule.toNot, captures, targetPath))
|
|
75
|
+
return false;
|
|
76
|
+
return true;
|
|
77
|
+
};
|
|
78
|
+
//# sourceMappingURL=patterns.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"patterns.js","sourceRoot":"","sources":["../../../src/core/patterns.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
import * as Result from "effect/Result";
|
|
2
|
+
import { compilePatterns } from "./patterns.js";
|
|
3
|
+
export const EMPTY_STRUCTURE = {
|
|
4
|
+
roots: [],
|
|
5
|
+
folders: [],
|
|
6
|
+
parity: [],
|
|
7
|
+
naming: [],
|
|
8
|
+
};
|
|
9
|
+
const compileRoot = (rule) => {
|
|
10
|
+
const path = compilePatterns(rule.name, "path", rule.path);
|
|
11
|
+
if (Result.isFailure(path))
|
|
12
|
+
return Result.fail(path.failure);
|
|
13
|
+
return Result.succeed({
|
|
14
|
+
name: rule.name,
|
|
15
|
+
message: rule.message,
|
|
16
|
+
path: path.success,
|
|
17
|
+
probe: rule.probe.path,
|
|
18
|
+
});
|
|
19
|
+
};
|
|
20
|
+
const compileFolder = (rule) => {
|
|
21
|
+
const folder = compilePatterns(rule.name, "folder", rule.folder);
|
|
22
|
+
if (Result.isFailure(folder))
|
|
23
|
+
return Result.fail(folder.failure);
|
|
24
|
+
const files = compilePatterns(rule.name, "files", rule.files);
|
|
25
|
+
if (Result.isFailure(files))
|
|
26
|
+
return Result.fail(files.failure);
|
|
27
|
+
return Result.succeed({
|
|
28
|
+
name: rule.name,
|
|
29
|
+
message: rule.message,
|
|
30
|
+
folder: folder.success,
|
|
31
|
+
files: files.success,
|
|
32
|
+
probe: rule.probe.path,
|
|
33
|
+
});
|
|
34
|
+
};
|
|
35
|
+
const compileParity = (rule) => {
|
|
36
|
+
const file = compilePatterns(rule.name, "file", rule.file);
|
|
37
|
+
if (Result.isFailure(file))
|
|
38
|
+
return Result.fail(file.failure);
|
|
39
|
+
const fileNot = compilePatterns(rule.name, "fileNot", rule.fileNot);
|
|
40
|
+
if (Result.isFailure(fileNot))
|
|
41
|
+
return Result.fail(fileNot.failure);
|
|
42
|
+
return Result.succeed({
|
|
43
|
+
name: rule.name,
|
|
44
|
+
message: rule.message,
|
|
45
|
+
file: file.success,
|
|
46
|
+
fileNot: fileNot.success,
|
|
47
|
+
requires: [...rule.requires],
|
|
48
|
+
probe: rule.probe.path,
|
|
49
|
+
});
|
|
50
|
+
};
|
|
51
|
+
const compileNaming = (rule) => {
|
|
52
|
+
const file = compilePatterns(rule.name, "file", rule.file);
|
|
53
|
+
if (Result.isFailure(file))
|
|
54
|
+
return Result.fail(file.failure);
|
|
55
|
+
const fileNot = compilePatterns(rule.name, "fileNot", rule.fileNot);
|
|
56
|
+
if (Result.isFailure(fileNot))
|
|
57
|
+
return Result.fail(fileNot.failure);
|
|
58
|
+
const convention = compilePatterns(rule.name, "convention", rule.convention);
|
|
59
|
+
if (Result.isFailure(convention))
|
|
60
|
+
return Result.fail(convention.failure);
|
|
61
|
+
return Result.succeed({
|
|
62
|
+
name: rule.name,
|
|
63
|
+
message: rule.message,
|
|
64
|
+
file: file.success,
|
|
65
|
+
fileNot: fileNot.success,
|
|
66
|
+
subject: rule.subject,
|
|
67
|
+
convention: convention.success[0] ?? null,
|
|
68
|
+
sameAs: rule.sameAs ?? null,
|
|
69
|
+
probe: rule.probe.path,
|
|
70
|
+
});
|
|
71
|
+
};
|
|
72
|
+
const compileAll = (items, compile) => {
|
|
73
|
+
const compiled = [];
|
|
74
|
+
for (const item of items) {
|
|
75
|
+
const one = compile(item);
|
|
76
|
+
if (Result.isFailure(one))
|
|
77
|
+
return Result.fail(one.failure);
|
|
78
|
+
compiled.push(one.success);
|
|
79
|
+
}
|
|
80
|
+
return Result.succeed(compiled);
|
|
81
|
+
};
|
|
82
|
+
export const compileStructure = (config) => {
|
|
83
|
+
if (config === undefined)
|
|
84
|
+
return Result.succeed(EMPTY_STRUCTURE);
|
|
85
|
+
const roots = compileAll(config.roots ?? [], compileRoot);
|
|
86
|
+
if (Result.isFailure(roots))
|
|
87
|
+
return Result.fail(roots.failure);
|
|
88
|
+
const folders = compileAll(config.folders ?? [], compileFolder);
|
|
89
|
+
if (Result.isFailure(folders))
|
|
90
|
+
return Result.fail(folders.failure);
|
|
91
|
+
const parity = compileAll(config.parity ?? [], compileParity);
|
|
92
|
+
if (Result.isFailure(parity))
|
|
93
|
+
return Result.fail(parity.failure);
|
|
94
|
+
const naming = compileAll(config.naming ?? [], compileNaming);
|
|
95
|
+
if (Result.isFailure(naming))
|
|
96
|
+
return Result.fail(naming.failure);
|
|
97
|
+
return Result.succeed({
|
|
98
|
+
roots: roots.success,
|
|
99
|
+
folders: folders.success,
|
|
100
|
+
parity: parity.success,
|
|
101
|
+
naming: naming.success,
|
|
102
|
+
});
|
|
103
|
+
};
|
|
104
|
+
const anyMatches = (patterns, value) => patterns.some((pattern) => pattern.test(value));
|
|
105
|
+
const dirnameOf = (file) => {
|
|
106
|
+
const cut = file.lastIndexOf("/");
|
|
107
|
+
return cut === -1 ? "" : file.slice(0, cut);
|
|
108
|
+
};
|
|
109
|
+
const basenameOf = (file) => file.slice(file.lastIndexOf("/") + 1);
|
|
110
|
+
// `{base}` is the filename minus its FINAL extension, so `create-todo.handler.ts`
|
|
111
|
+
// yields `create-todo.handler` and `{base}.test.ts` names its sibling test. The
|
|
112
|
+
// dot-delimited stereotype stays part of the base on purpose.
|
|
113
|
+
const baseOf = (basename) => {
|
|
114
|
+
const cut = basename.lastIndexOf(".");
|
|
115
|
+
return cut <= 0 ? basename : basename.slice(0, cut);
|
|
116
|
+
};
|
|
117
|
+
// A `../` in a required path is resolved against the file's own folder, which is
|
|
118
|
+
// how a port three folders from its adapters names them.
|
|
119
|
+
const resolveSibling = (folder, relative) => {
|
|
120
|
+
const segments = folder === "" ? [] : folder.split("/");
|
|
121
|
+
for (const segment of relative.split("/")) {
|
|
122
|
+
if (segment === "..")
|
|
123
|
+
segments.pop();
|
|
124
|
+
else if (segment !== "." && segment !== "")
|
|
125
|
+
segments.push(segment);
|
|
126
|
+
}
|
|
127
|
+
return segments.join("/");
|
|
128
|
+
};
|
|
129
|
+
export const requiredSiblingsOf = (rule, file) => {
|
|
130
|
+
const base = baseOf(basenameOf(file));
|
|
131
|
+
const folder = dirnameOf(file);
|
|
132
|
+
return rule.requires.map((template) => resolveSibling(folder, template.replaceAll("{base}", base)));
|
|
133
|
+
};
|
|
134
|
+
// The rule's pattern carries capture groups; `subject` says which one holds the
|
|
135
|
+
// name being judged, and `sameAs` which one it has to equal.
|
|
136
|
+
const firstNamingMatch = (rule, file) => {
|
|
137
|
+
for (const pattern of rule.file) {
|
|
138
|
+
const found = pattern.exec(file);
|
|
139
|
+
if (found === null)
|
|
140
|
+
continue;
|
|
141
|
+
const subject = found[rule.subject];
|
|
142
|
+
if (subject === undefined)
|
|
143
|
+
continue;
|
|
144
|
+
return {
|
|
145
|
+
subject,
|
|
146
|
+
expected: rule.sameAs === null ? null : (found[rule.sameAs] ?? null),
|
|
147
|
+
comparing: rule.sameAs !== null,
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
return null;
|
|
151
|
+
};
|
|
152
|
+
const namingSatisfied = (rule, named) => named.comparing
|
|
153
|
+
? named.expected !== null && named.subject === named.expected
|
|
154
|
+
: rule.convention === null || rule.convention.test(named.subject);
|
|
155
|
+
export const evaluateStructure = (structure, fileSystem, file) => {
|
|
156
|
+
const violations = [];
|
|
157
|
+
const folder = dirnameOf(file);
|
|
158
|
+
const basename = basenameOf(file);
|
|
159
|
+
for (const rule of structure.parity) {
|
|
160
|
+
if (!anyMatches(rule.file, file) || anyMatches(rule.fileNot, file))
|
|
161
|
+
continue;
|
|
162
|
+
for (const sibling of requiredSiblingsOf(rule, file)) {
|
|
163
|
+
if (fileSystem.exists(sibling))
|
|
164
|
+
continue;
|
|
165
|
+
violations.push({
|
|
166
|
+
kind: "structure",
|
|
167
|
+
ruleName: rule.name,
|
|
168
|
+
message: rule.message,
|
|
169
|
+
file,
|
|
170
|
+
subject: sibling,
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
for (const rule of structure.naming) {
|
|
175
|
+
if (anyMatches(rule.fileNot, file))
|
|
176
|
+
continue;
|
|
177
|
+
const named = firstNamingMatch(rule, file);
|
|
178
|
+
if (named === null || namingSatisfied(rule, named))
|
|
179
|
+
continue;
|
|
180
|
+
violations.push({
|
|
181
|
+
kind: "structure",
|
|
182
|
+
ruleName: rule.name,
|
|
183
|
+
message: rule.message,
|
|
184
|
+
file,
|
|
185
|
+
subject: named.subject,
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
const governing = structure.folders.filter((rule) => anyMatches(rule.folder, folder));
|
|
189
|
+
if (governing.length > 0) {
|
|
190
|
+
if (!governing.some((rule) => anyMatches(rule.files, basename))) {
|
|
191
|
+
const rule = governing[0];
|
|
192
|
+
if (rule !== undefined) {
|
|
193
|
+
violations.push({
|
|
194
|
+
kind: "structure",
|
|
195
|
+
ruleName: rule.name,
|
|
196
|
+
message: rule.message,
|
|
197
|
+
file,
|
|
198
|
+
subject: basename,
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
return violations;
|
|
203
|
+
}
|
|
204
|
+
// No folder rule governs this folder at all. Inside a taxonomy root that means
|
|
205
|
+
// the folder itself is not part of the taxonomy — the stray-folder case a
|
|
206
|
+
// per-file check would otherwise miss entirely.
|
|
207
|
+
const root = structure.roots.find((candidate) => anyMatches(candidate.path, file));
|
|
208
|
+
if (root !== undefined) {
|
|
209
|
+
violations.push({
|
|
210
|
+
kind: "structure",
|
|
211
|
+
ruleName: root.name,
|
|
212
|
+
message: root.message,
|
|
213
|
+
file,
|
|
214
|
+
subject: folder,
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
return violations;
|
|
218
|
+
};
|
|
219
|
+
// A structure rule proves itself the same way the other families do: on a path
|
|
220
|
+
// it must reject. Parity is checked structurally — that the rule still selects
|
|
221
|
+
// its probe and still renders a sibling to demand — because asking the real
|
|
222
|
+
// filesystem at config-load time would make the guard depend on a fixture.
|
|
223
|
+
export const structureRulesFailingTheirProbe = (structure) => {
|
|
224
|
+
const failing = [];
|
|
225
|
+
for (const rule of structure.naming) {
|
|
226
|
+
const named = firstNamingMatch(rule, rule.probe);
|
|
227
|
+
if (named === null || namingSatisfied(rule, named) || anyMatches(rule.fileNot, rule.probe)) {
|
|
228
|
+
failing.push(rule.name);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
for (const rule of structure.parity) {
|
|
232
|
+
const selects = anyMatches(rule.file, rule.probe) && !anyMatches(rule.fileNot, rule.probe);
|
|
233
|
+
const demands = requiredSiblingsOf(rule, rule.probe).some((sibling) => sibling.length > 0);
|
|
234
|
+
if (!selects || !demands)
|
|
235
|
+
failing.push(rule.name);
|
|
236
|
+
}
|
|
237
|
+
const layoutOnly = { ...structure, parity: [] };
|
|
238
|
+
const reported = (file) => evaluateStructure(layoutOnly, { exists: () => true }, file).map((violation) => violation.ruleName);
|
|
239
|
+
for (const rule of structure.folders) {
|
|
240
|
+
// A folder that admits any name claims its folder but states no policy, so
|
|
241
|
+
// there is nothing for a probe to demonstrate.
|
|
242
|
+
if (rule.files.some((pattern) => pattern.source === "^.*$"))
|
|
243
|
+
continue;
|
|
244
|
+
// The rule must govern its probe's folder AND the folder's admitted set —
|
|
245
|
+
// the union of every governing rule — must still reject the basename.
|
|
246
|
+
const governs = anyMatches(rule.folder, dirnameOf(rule.probe));
|
|
247
|
+
if (!governs || reported(rule.probe).length === 0)
|
|
248
|
+
failing.push(rule.name);
|
|
249
|
+
}
|
|
250
|
+
for (const rule of structure.roots) {
|
|
251
|
+
if (!reported(rule.probe).includes(rule.name))
|
|
252
|
+
failing.push(rule.name);
|
|
253
|
+
}
|
|
254
|
+
return failing;
|
|
255
|
+
};
|
|
256
|
+
//# sourceMappingURL=structure.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"structure.js","sourceRoot":"","sources":["../../../src/core/structure.ts"],"names":[],"mappings":"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"}
|