@goodbones/core 0.1.0-beta.1
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/core/baseline.d.ts +16 -0
- package/build/dts/core/baseline.d.ts.map +1 -0
- package/build/dts/core/coverage.d.ts +47 -0
- package/build/dts/core/coverage.d.ts.map +1 -0
- package/build/dts/core/exports.d.ts +38 -0
- package/build/dts/core/exports.d.ts.map +1 -0
- package/build/dts/core/graph.d.ts +40 -0
- package/build/dts/core/graph.d.ts.map +1 -0
- package/build/dts/core/imports.d.ts +29 -0
- package/build/dts/core/imports.d.ts.map +1 -0
- package/build/dts/core/members.d.ts +26 -0
- package/build/dts/core/members.d.ts.map +1 -0
- package/build/dts/core/patterns.d.ts +17 -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/core/surface.d.ts +39 -0
- package/build/dts/core/surface.d.ts.map +1 -0
- package/build/dts/domain/architecture-config.d.ts +322 -0
- package/build/dts/domain/architecture-config.d.ts.map +1 -0
- package/build/dts/domain/architecture-error.d.ts +35 -0
- package/build/dts/domain/architecture-error.d.ts.map +1 -0
- package/build/dts/domain/facts.d.ts +26 -0
- package/build/dts/domain/facts.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 +23 -0
- package/build/dts/index.d.ts.map +1 -0
- package/build/dts/infrastructure/fact-extractor-fake.d.ts +4 -0
- package/build/dts/infrastructure/fact-extractor-fake.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/manifest-file.d.ts +3 -0
- package/build/dts/infrastructure/manifest-file.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/walk.d.ts +4 -0
- package/build/dts/infrastructure/walk.d.ts.map +1 -0
- package/build/dts/load/policy.d.ts +42 -0
- package/build/dts/load/policy.d.ts.map +1 -0
- package/build/dts/manifest/compile.d.ts +26 -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 +208 -0
- package/build/dts/manifest/manifest.d.ts.map +1 -0
- package/build/dts/ports/fact-extractor.d.ts +5 -0
- package/build/dts/ports/fact-extractor.d.ts.map +1 -0
- package/build/dts/ports/file-system.d.ts +5 -0
- package/build/dts/ports/file-system.d.ts.map +1 -0
- package/build/dts/ports/language.d.ts +14 -0
- package/build/dts/ports/language.d.ts.map +1 -0
- package/build/dts/ports/module-resolver.d.ts +12 -0
- package/build/dts/ports/module-resolver.d.ts.map +1 -0
- package/build/dts/testing.d.ts +4 -0
- package/build/dts/testing.d.ts.map +1 -0
- package/build/esm/core/baseline.js +30 -0
- package/build/esm/core/baseline.js.map +1 -0
- package/build/esm/core/coverage.js +75 -0
- package/build/esm/core/coverage.js.map +1 -0
- package/build/esm/core/exports.js +102 -0
- package/build/esm/core/exports.js.map +1 -0
- package/build/esm/core/graph.js +259 -0
- package/build/esm/core/graph.js.map +1 -0
- package/build/esm/core/imports.js +103 -0
- package/build/esm/core/imports.js.map +1 -0
- package/build/esm/core/members.js +106 -0
- package/build/esm/core/members.js.map +1 -0
- package/build/esm/core/patterns.js +75 -0
- package/build/esm/core/patterns.js.map +1 -0
- package/build/esm/core/structure.js +257 -0
- package/build/esm/core/structure.js.map +1 -0
- package/build/esm/core/surface.js +137 -0
- package/build/esm/core/surface.js.map +1 -0
- package/build/esm/domain/architecture-config.js +312 -0
- package/build/esm/domain/architecture-config.js.map +1 -0
- package/build/esm/domain/architecture-error.js +41 -0
- package/build/esm/domain/architecture-error.js.map +1 -0
- package/build/esm/domain/facts.js +2 -0
- package/build/esm/domain/facts.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 +22 -0
- package/build/esm/index.js.map +1 -0
- package/build/esm/infrastructure/fact-extractor-fake.js +24 -0
- package/build/esm/infrastructure/fact-extractor-fake.js.map +1 -0
- package/build/esm/infrastructure/file-system-fake.js +10 -0
- package/build/esm/infrastructure/file-system-fake.js.map +1 -0
- package/build/esm/infrastructure/file-system-live.js +27 -0
- package/build/esm/infrastructure/file-system-live.js.map +1 -0
- package/build/esm/infrastructure/manifest-file.js +15 -0
- package/build/esm/infrastructure/manifest-file.js.map +1 -0
- package/build/esm/infrastructure/module-resolver-fake.js +33 -0
- package/build/esm/infrastructure/module-resolver-fake.js.map +1 -0
- package/build/esm/infrastructure/walk.js +45 -0
- package/build/esm/infrastructure/walk.js.map +1 -0
- package/build/esm/load/policy.js +207 -0
- package/build/esm/load/policy.js.map +1 -0
- package/build/esm/manifest/compile.js +706 -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 +303 -0
- package/build/esm/manifest/manifest.js.map +1 -0
- package/build/esm/ports/fact-extractor.js +2 -0
- package/build/esm/ports/fact-extractor.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/language.js +2 -0
- package/build/esm/ports/language.js.map +1 -0
- package/build/esm/ports/module-resolver.js +2 -0
- package/build/esm/ports/module-resolver.js.map +1 -0
- package/build/esm/testing.js +7 -0
- package/build/esm/testing.js.map +1 -0
- package/package.json +61 -0
- package/src/core/baseline.ts +62 -0
- package/src/core/coverage.ts +154 -0
- package/src/core/exports.ts +171 -0
- package/src/core/graph.ts +331 -0
- package/src/core/imports.ts +160 -0
- package/src/core/members.ts +161 -0
- package/src/core/patterns.ts +116 -0
- package/src/core/structure.ts +349 -0
- package/src/core/surface.ts +181 -0
- package/src/domain/architecture-config.ts +370 -0
- package/src/domain/architecture-error.ts +59 -0
- package/src/domain/facts.ts +47 -0
- package/src/domain/violation.ts +24 -0
- package/src/index.ts +136 -0
- package/src/infrastructure/fact-extractor-fake.ts +28 -0
- package/src/infrastructure/file-system-fake.ts +14 -0
- package/src/infrastructure/file-system-live.ts +27 -0
- package/src/infrastructure/manifest-file.ts +17 -0
- package/src/infrastructure/module-resolver-fake.ts +39 -0
- package/src/infrastructure/walk.ts +54 -0
- package/src/load/policy.ts +344 -0
- package/src/manifest/compile.ts +1011 -0
- package/src/manifest/glob.ts +108 -0
- package/src/manifest/manifest.ts +408 -0
- package/src/ports/fact-extractor.ts +12 -0
- package/src/ports/file-system.ts +8 -0
- package/src/ports/language.ts +39 -0
- package/src/ports/module-resolver.ts +28 -0
- package/src/testing.ts +6 -0
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
import * as Result from "effect/Result";
|
|
2
|
+
import { compilePatterns } from "./patterns.js";
|
|
3
|
+
export const EMPTY_GRAPH_RULES = { cycles: [], orphans: [], reach: [] };
|
|
4
|
+
export const hasGraphRules = (rules) => rules.cycles.length + rules.orphans.length + rules.reach.length > 0;
|
|
5
|
+
const compileFields = (ruleName, fields) => {
|
|
6
|
+
const compiled = [];
|
|
7
|
+
for (const [field, patterns] of fields) {
|
|
8
|
+
const one = compilePatterns(ruleName, field, patterns);
|
|
9
|
+
if (Result.isFailure(one))
|
|
10
|
+
return Result.fail(one.failure);
|
|
11
|
+
compiled.push(one.success);
|
|
12
|
+
}
|
|
13
|
+
return Result.succeed(compiled);
|
|
14
|
+
};
|
|
15
|
+
const compileCycle = (rule) => {
|
|
16
|
+
const fields = compileFields(rule.name, [
|
|
17
|
+
["within", rule.within],
|
|
18
|
+
["withinNot", rule.withinNot],
|
|
19
|
+
]);
|
|
20
|
+
if (Result.isFailure(fields))
|
|
21
|
+
return Result.fail(fields.failure);
|
|
22
|
+
const [within = [], withinNot = []] = fields.success;
|
|
23
|
+
return Result.succeed({
|
|
24
|
+
name: rule.name,
|
|
25
|
+
message: rule.message,
|
|
26
|
+
probe: rule.probe,
|
|
27
|
+
within,
|
|
28
|
+
withinNot,
|
|
29
|
+
});
|
|
30
|
+
};
|
|
31
|
+
const compileOrphan = (rule) => {
|
|
32
|
+
const fields = compileFields(rule.name, [
|
|
33
|
+
["within", rule.within],
|
|
34
|
+
["withinNot", rule.withinNot],
|
|
35
|
+
["entry", rule.entry],
|
|
36
|
+
]);
|
|
37
|
+
if (Result.isFailure(fields))
|
|
38
|
+
return Result.fail(fields.failure);
|
|
39
|
+
const [within = [], withinNot = [], entry = []] = fields.success;
|
|
40
|
+
return Result.succeed({
|
|
41
|
+
name: rule.name,
|
|
42
|
+
message: rule.message,
|
|
43
|
+
probe: rule.probe,
|
|
44
|
+
within,
|
|
45
|
+
withinNot,
|
|
46
|
+
entry,
|
|
47
|
+
});
|
|
48
|
+
};
|
|
49
|
+
const compileReach = (rule) => {
|
|
50
|
+
const fields = compileFields(rule.name, [
|
|
51
|
+
["from", rule.from],
|
|
52
|
+
["fromNot", rule.fromNot],
|
|
53
|
+
["to", rule.to],
|
|
54
|
+
["toNot", rule.toNot],
|
|
55
|
+
["via", rule.via],
|
|
56
|
+
]);
|
|
57
|
+
if (Result.isFailure(fields))
|
|
58
|
+
return Result.fail(fields.failure);
|
|
59
|
+
const [from = [], fromNot = [], to = [], toNot = [], via = []] = fields.success;
|
|
60
|
+
return Result.succeed({
|
|
61
|
+
name: rule.name,
|
|
62
|
+
message: rule.message,
|
|
63
|
+
probe: rule.probe,
|
|
64
|
+
from,
|
|
65
|
+
fromNot,
|
|
66
|
+
to,
|
|
67
|
+
toNot,
|
|
68
|
+
via,
|
|
69
|
+
});
|
|
70
|
+
};
|
|
71
|
+
export const compileGraphRules = (config) => {
|
|
72
|
+
const cycles = [];
|
|
73
|
+
for (const rule of config?.cycles ?? []) {
|
|
74
|
+
const one = compileCycle(rule);
|
|
75
|
+
if (Result.isFailure(one))
|
|
76
|
+
return Result.fail(one.failure);
|
|
77
|
+
cycles.push(one.success);
|
|
78
|
+
}
|
|
79
|
+
const orphans = [];
|
|
80
|
+
for (const rule of config?.orphans ?? []) {
|
|
81
|
+
const one = compileOrphan(rule);
|
|
82
|
+
if (Result.isFailure(one))
|
|
83
|
+
return Result.fail(one.failure);
|
|
84
|
+
orphans.push(one.success);
|
|
85
|
+
}
|
|
86
|
+
const reach = [];
|
|
87
|
+
for (const rule of config?.reach ?? []) {
|
|
88
|
+
const one = compileReach(rule);
|
|
89
|
+
if (Result.isFailure(one))
|
|
90
|
+
return Result.fail(one.failure);
|
|
91
|
+
reach.push(one.success);
|
|
92
|
+
}
|
|
93
|
+
return Result.succeed({ cycles, orphans, reach });
|
|
94
|
+
};
|
|
95
|
+
const anyMatches = (patterns, value) => patterns.some((pattern) => pattern.test(value));
|
|
96
|
+
const inScope = (scope, file) => anyMatches(scope.within, file) && !anyMatches(scope.withinNot, file);
|
|
97
|
+
// Sorted adjacency, so every traversal below is deterministic and a subject
|
|
98
|
+
// rendered from it is the same on every run.
|
|
99
|
+
const neighboursOf = (graph, file) => [...(graph.edges.get(file) ?? [])].sort();
|
|
100
|
+
// Tarjan's strongly connected components over the subgraph a rule is about.
|
|
101
|
+
// A component of one node is a cycle only if that node imports itself.
|
|
102
|
+
const stronglyConnected = (nodes, graph) => {
|
|
103
|
+
const members = new Set(nodes);
|
|
104
|
+
const index = new Map();
|
|
105
|
+
const low = new Map();
|
|
106
|
+
const onStack = new Set();
|
|
107
|
+
const stack = [];
|
|
108
|
+
const components = [];
|
|
109
|
+
let next = 0;
|
|
110
|
+
const visit = (node) => {
|
|
111
|
+
index.set(node, next);
|
|
112
|
+
low.set(node, next);
|
|
113
|
+
next += 1;
|
|
114
|
+
stack.push(node);
|
|
115
|
+
onStack.add(node);
|
|
116
|
+
for (const target of neighboursOf(graph, node)) {
|
|
117
|
+
if (!members.has(target))
|
|
118
|
+
continue;
|
|
119
|
+
if (!index.has(target)) {
|
|
120
|
+
visit(target);
|
|
121
|
+
low.set(node, Math.min(low.get(node) ?? 0, low.get(target) ?? 0));
|
|
122
|
+
}
|
|
123
|
+
else if (onStack.has(target)) {
|
|
124
|
+
low.set(node, Math.min(low.get(node) ?? 0, index.get(target) ?? 0));
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
if (low.get(node) === index.get(node)) {
|
|
128
|
+
const component = [];
|
|
129
|
+
let popped;
|
|
130
|
+
do {
|
|
131
|
+
popped = stack.pop();
|
|
132
|
+
if (popped === undefined)
|
|
133
|
+
break;
|
|
134
|
+
onStack.delete(popped);
|
|
135
|
+
component.push(popped);
|
|
136
|
+
} while (popped !== node);
|
|
137
|
+
components.push(component.sort());
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
for (const node of [...nodes].sort())
|
|
141
|
+
if (!index.has(node))
|
|
142
|
+
visit(node);
|
|
143
|
+
return components;
|
|
144
|
+
};
|
|
145
|
+
const evaluateCycles = (rule, graph) => {
|
|
146
|
+
const nodes = graph.files.filter((file) => inScope(rule, file));
|
|
147
|
+
const violations = [];
|
|
148
|
+
for (const component of stronglyConnected(nodes, graph)) {
|
|
149
|
+
const [first] = component;
|
|
150
|
+
if (first === undefined)
|
|
151
|
+
continue;
|
|
152
|
+
const isCycle = component.length > 1 || (graph.edges.get(first) ?? []).includes(first);
|
|
153
|
+
if (!isCycle)
|
|
154
|
+
continue;
|
|
155
|
+
// The subject is the component as a set, so the entry survives an edge
|
|
156
|
+
// added or removed elsewhere in the same cycle.
|
|
157
|
+
violations.push({
|
|
158
|
+
kind: "graph",
|
|
159
|
+
ruleName: rule.name,
|
|
160
|
+
message: rule.message,
|
|
161
|
+
file: first,
|
|
162
|
+
subject: component.join(" ↔ "),
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
return violations;
|
|
166
|
+
};
|
|
167
|
+
const evaluateOrphans = (rule, graph) => {
|
|
168
|
+
const imported = new Set();
|
|
169
|
+
for (const targets of graph.edges.values())
|
|
170
|
+
for (const target of targets)
|
|
171
|
+
imported.add(target);
|
|
172
|
+
return graph.files
|
|
173
|
+
.filter((file) => inScope(rule, file) && !anyMatches(rule.entry, file) && !imported.has(file))
|
|
174
|
+
.map((file) => ({
|
|
175
|
+
kind: "graph",
|
|
176
|
+
ruleName: rule.name,
|
|
177
|
+
message: rule.message,
|
|
178
|
+
file,
|
|
179
|
+
subject: null,
|
|
180
|
+
}));
|
|
181
|
+
};
|
|
182
|
+
// Breadth-first from each `from` file, never stepping onto a `via` node, so a
|
|
183
|
+
// `to` reached is one reached without passing through the tier that was
|
|
184
|
+
// supposed to mediate. The route is put in the message, not the subject: the
|
|
185
|
+
// fingerprint is (from, to), which survives the route changing.
|
|
186
|
+
const evaluateReach = (rule, graph) => {
|
|
187
|
+
const violations = [];
|
|
188
|
+
const isTarget = (file) => anyMatches(rule.to, file) && !anyMatches(rule.toNot, file);
|
|
189
|
+
for (const origin of graph.files) {
|
|
190
|
+
if (!anyMatches(rule.from, origin) || anyMatches(rule.fromNot, origin))
|
|
191
|
+
continue;
|
|
192
|
+
const parent = new Map();
|
|
193
|
+
const queue = [origin];
|
|
194
|
+
const seen = new Set([origin]);
|
|
195
|
+
const reported = new Set();
|
|
196
|
+
while (queue.length > 0) {
|
|
197
|
+
const node = queue.shift();
|
|
198
|
+
if (node === undefined)
|
|
199
|
+
break;
|
|
200
|
+
for (const target of neighboursOf(graph, node)) {
|
|
201
|
+
if (seen.has(target))
|
|
202
|
+
continue;
|
|
203
|
+
if (anyMatches(rule.via, target))
|
|
204
|
+
continue;
|
|
205
|
+
seen.add(target);
|
|
206
|
+
parent.set(target, node);
|
|
207
|
+
if (isTarget(target) && !reported.has(target)) {
|
|
208
|
+
reported.add(target);
|
|
209
|
+
const route = [target];
|
|
210
|
+
let step = target;
|
|
211
|
+
while (step !== undefined && step !== origin) {
|
|
212
|
+
step = parent.get(step);
|
|
213
|
+
if (step !== undefined)
|
|
214
|
+
route.unshift(step);
|
|
215
|
+
}
|
|
216
|
+
violations.push({
|
|
217
|
+
kind: "graph",
|
|
218
|
+
ruleName: rule.name,
|
|
219
|
+
message: `${rule.message} (route: ${route.join(" → ")})`,
|
|
220
|
+
file: origin,
|
|
221
|
+
subject: target,
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
queue.push(target);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
return violations;
|
|
229
|
+
};
|
|
230
|
+
export const evaluateGraph = (rules, graph) => [
|
|
231
|
+
...rules.cycles.flatMap((rule) => evaluateCycles(rule, graph)),
|
|
232
|
+
...rules.orphans.flatMap((rule) => evaluateOrphans(rule, graph)),
|
|
233
|
+
...rules.reach.flatMap((rule) => evaluateReach(rule, graph)),
|
|
234
|
+
];
|
|
235
|
+
// A probe is a small synthetic graph the rule must report on.
|
|
236
|
+
export const graphOf = (probe) => {
|
|
237
|
+
const edges = new Map();
|
|
238
|
+
const files = new Set(probe.files ?? []);
|
|
239
|
+
for (const [from, to] of probe.edges) {
|
|
240
|
+
files.add(from);
|
|
241
|
+
files.add(to);
|
|
242
|
+
const targets = edges.get(from) ?? [];
|
|
243
|
+
targets.push(to);
|
|
244
|
+
edges.set(from, targets);
|
|
245
|
+
}
|
|
246
|
+
return { files: [...files].sort(), edges };
|
|
247
|
+
};
|
|
248
|
+
export const graphRulesFailingTheirProbe = (rules) => [
|
|
249
|
+
...rules.cycles
|
|
250
|
+
.filter((rule) => evaluateCycles(rule, graphOf(rule.probe)).length === 0)
|
|
251
|
+
.map((rule) => rule.name),
|
|
252
|
+
...rules.orphans
|
|
253
|
+
.filter((rule) => evaluateOrphans(rule, graphOf(rule.probe)).length === 0)
|
|
254
|
+
.map((rule) => rule.name),
|
|
255
|
+
...rules.reach
|
|
256
|
+
.filter((rule) => evaluateReach(rule, graphOf(rule.probe)).length === 0)
|
|
257
|
+
.map((rule) => rule.name),
|
|
258
|
+
];
|
|
259
|
+
//# sourceMappingURL=graph.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graph.js","sourceRoot":"","sources":["../../../src/core/graph.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import * as Result from "effect/Result";
|
|
2
|
+
import { compilePatterns, firstFromMatch, 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
|
+
externals: new Set(rule.externals ?? []),
|
|
25
|
+
dependencyKind: rule.dependencyKind ?? null,
|
|
26
|
+
});
|
|
27
|
+
};
|
|
28
|
+
export const compileImportRules = (rules) => {
|
|
29
|
+
const compiled = [];
|
|
30
|
+
for (const rule of rules) {
|
|
31
|
+
const one = compileImportRule(rule);
|
|
32
|
+
if (Result.isFailure(one))
|
|
33
|
+
return Result.fail(one.failure);
|
|
34
|
+
compiled.push(one.success);
|
|
35
|
+
}
|
|
36
|
+
return Result.succeed(compiled);
|
|
37
|
+
};
|
|
38
|
+
// Returns the rules whose `from` side selects this file. A file no rule selects
|
|
39
|
+
// never needs its imports resolved, which is what keeps resolution off the hot
|
|
40
|
+
// path for the bulk of the repo.
|
|
41
|
+
export const rulesSelecting = (rules, importer) => {
|
|
42
|
+
const selected = [];
|
|
43
|
+
for (const rule of rules) {
|
|
44
|
+
const captures = firstFromMatch(rule, importer);
|
|
45
|
+
if (captures !== null)
|
|
46
|
+
selected.push([rule, captures]);
|
|
47
|
+
}
|
|
48
|
+
return selected;
|
|
49
|
+
};
|
|
50
|
+
// Whether the rule reports this target. The kind comes from the resolver, an
|
|
51
|
+
// external is judged by its package name, and only then do the path patterns
|
|
52
|
+
// speak — so a rule never has to know where a language keeps its packages.
|
|
53
|
+
const reports = (rule, captures, target) => {
|
|
54
|
+
if (rule.dependencyKind !== null && rule.dependencyKind !== target.kind)
|
|
55
|
+
return false;
|
|
56
|
+
if (target.kind === "external" &&
|
|
57
|
+
target.package !== undefined &&
|
|
58
|
+
rule.externals.has(target.package)) {
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
return targetAllowed(rule, captures, target.path);
|
|
62
|
+
};
|
|
63
|
+
export const evaluateSelectedEdge = (selected, resolver, edge) => {
|
|
64
|
+
if (selected.length === 0)
|
|
65
|
+
return Result.succeed([]);
|
|
66
|
+
const resolved = resolver.resolve(edge.importer, edge.specifier);
|
|
67
|
+
if (Result.isFailure(resolved))
|
|
68
|
+
return Result.fail(resolved.failure);
|
|
69
|
+
const target = resolved.success;
|
|
70
|
+
const violations = [];
|
|
71
|
+
for (const [rule, captures] of selected) {
|
|
72
|
+
if (reports(rule, captures, target)) {
|
|
73
|
+
violations.push({
|
|
74
|
+
kind: "import",
|
|
75
|
+
ruleName: rule.name,
|
|
76
|
+
message: rule.message,
|
|
77
|
+
file: edge.importer,
|
|
78
|
+
subject: target.path,
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return Result.succeed(violations);
|
|
83
|
+
};
|
|
84
|
+
export const evaluateImportEdge = (rules, resolver, edge) => evaluateSelectedEdge(rulesSelecting(rules, edge.importer), resolver, edge);
|
|
85
|
+
// A probe states its target in one of three forms, and the form is the kind —
|
|
86
|
+
// so the probe never has to know how a language spells an external's path.
|
|
87
|
+
export const probeTargetOf = (to) => {
|
|
88
|
+
if (typeof to === "string")
|
|
89
|
+
return { path: to, kind: "local" };
|
|
90
|
+
if ("external" in to)
|
|
91
|
+
return { path: to.external, kind: "external", package: to.external };
|
|
92
|
+
return { path: to.builtin, kind: "builtin" };
|
|
93
|
+
};
|
|
94
|
+
// Every rule must report its own probe. A rule that does not is enforcing
|
|
95
|
+
// nothing while still looking configured and still passing a clean lint run —
|
|
96
|
+
// the one failure mode a linter cannot surface on its own.
|
|
97
|
+
export const rulesFailingTheirProbe = (rules) => rules.filter((rule) => {
|
|
98
|
+
const captures = firstFromMatch(rule, rule.probe.from);
|
|
99
|
+
if (captures === null)
|
|
100
|
+
return true;
|
|
101
|
+
return !reports(rule, captures, probeTargetOf(rule.probe.to));
|
|
102
|
+
});
|
|
103
|
+
//# 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,106 @@
|
|
|
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
|
+
declares: rule.declares === undefined ? null : [...rule.declares],
|
|
29
|
+
match,
|
|
30
|
+
matchNot,
|
|
31
|
+
allow,
|
|
32
|
+
});
|
|
33
|
+
};
|
|
34
|
+
export const compileMemberRules = (rules) => {
|
|
35
|
+
const compiled = [];
|
|
36
|
+
for (const rule of rules) {
|
|
37
|
+
const one = compileMemberRule(rule);
|
|
38
|
+
if (Result.isFailure(one))
|
|
39
|
+
return Result.fail(one.failure);
|
|
40
|
+
compiled.push(one.success);
|
|
41
|
+
}
|
|
42
|
+
return Result.succeed(compiled);
|
|
43
|
+
};
|
|
44
|
+
const anyMatches = (patterns, value) => patterns.some((pattern) => pattern.test(value));
|
|
45
|
+
export const memberRulesSelecting = (rules, file) => rules.filter((rule) => firstFromMatch(rule, file) !== null);
|
|
46
|
+
const governs = (rule, site) => {
|
|
47
|
+
if (rule.subject !== site.subject)
|
|
48
|
+
return false;
|
|
49
|
+
if (rule.in.length > 0 && (site.in === undefined || !anyMatches(rule.in, site.in)))
|
|
50
|
+
return false;
|
|
51
|
+
if (rule.declares !== null &&
|
|
52
|
+
(site.declares === undefined || !rule.declares.includes(site.declares))) {
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
if (rule.match.length > 0 && !anyMatches(rule.match, site.name))
|
|
56
|
+
return false;
|
|
57
|
+
if (rule.matchNot.length > 0 && anyMatches(rule.matchNot, site.name))
|
|
58
|
+
return false;
|
|
59
|
+
return true;
|
|
60
|
+
};
|
|
61
|
+
export const evaluateMemberSite = (selected, site) => {
|
|
62
|
+
const violations = [];
|
|
63
|
+
for (const rule of selected) {
|
|
64
|
+
if (!governs(rule, site))
|
|
65
|
+
continue;
|
|
66
|
+
if (anyMatches(rule.allow, site.name))
|
|
67
|
+
continue;
|
|
68
|
+
violations.push({
|
|
69
|
+
kind: "member",
|
|
70
|
+
ruleName: rule.name,
|
|
71
|
+
message: rule.message,
|
|
72
|
+
file: site.file,
|
|
73
|
+
subject: site.name,
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
return violations;
|
|
77
|
+
};
|
|
78
|
+
// A probe with a `source` is checked through the parser: the snippet must
|
|
79
|
+
// yield a site named `probe.name` that the rule reports. That is the check a
|
|
80
|
+
// synthetic site cannot make — a rule about a declaration shape the extractor
|
|
81
|
+
// does not read passes its synthetic probe and reports nothing. A probe
|
|
82
|
+
// without a source is checked against the rule's patterns alone, as a site
|
|
83
|
+
// declared in the first kind the rule speaks to.
|
|
84
|
+
export const memberRulesFailingTheirProbe = (rules, extractor) => rules.filter((rule) => {
|
|
85
|
+
if (firstFromMatch(rule, rule.probe.from) === null)
|
|
86
|
+
return true;
|
|
87
|
+
const sites = rule.probe.source === undefined
|
|
88
|
+
? [
|
|
89
|
+
{
|
|
90
|
+
file: rule.probe.from,
|
|
91
|
+
subject: rule.subject,
|
|
92
|
+
name: rule.probe.name,
|
|
93
|
+
...(rule.probe.in === undefined ? {} : { in: rule.probe.in }),
|
|
94
|
+
...(rule.probe.declares === undefined
|
|
95
|
+
? rule.declares === null
|
|
96
|
+
? {}
|
|
97
|
+
: { declares: rule.declares[0] }
|
|
98
|
+
: { declares: rule.probe.declares }),
|
|
99
|
+
},
|
|
100
|
+
]
|
|
101
|
+
: extractor
|
|
102
|
+
.factsOf(rule.probe.from, rule.probe.source)
|
|
103
|
+
.memberSites.filter((site) => site.name === rule.probe.name);
|
|
104
|
+
return !sites.some((site) => evaluateMemberSite([rule], site).length > 0);
|
|
105
|
+
});
|
|
106
|
+
//# 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,75 @@
|
|
|
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
|
+
export const targetAllowed = (rule, captures, targetPath) => {
|
|
69
|
+
if (rule.to.length > 0 && !matchesAny(rule.to, captures, targetPath))
|
|
70
|
+
return false;
|
|
71
|
+
if (rule.toNot.length > 0 && matchesAny(rule.toNot, captures, targetPath))
|
|
72
|
+
return false;
|
|
73
|
+
return true;
|
|
74
|
+
};
|
|
75
|
+
//# sourceMappingURL=patterns.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"patterns.js","sourceRoot":"","sources":["../../../src/core/patterns.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAExC,OAAO,EAAE,UAAU,EAAE,MAAM,kCAAkC,CAAC;AAC9D,OAAO,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AAEjE,MAAM,aAAa,GAAG,YAAY,CAAC;AAEnC,iFAAiF;AACjF,+CAA+C;AAC/C,MAAM,uBAAuB,GAAG,CAAC,OAAe,EAAU,EAAE,CAAC,OAAO,CAAC,UAAU,CAAC,aAAa,EAAE,GAAG,CAAC,CAAC;AAEpG,MAAM,cAAc,GAAG,CACrB,QAAgB,EAChB,KAAa,EACb,OAAe,EACwB,EAAE;IACzC,IAAI,CAAC;QACH,OAAO,MAAM,CAAC,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;IAC7C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,cAAc,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;IAC9F,CAAC;AACH,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,eAAe,GAAG,CAC7B,QAAgB,EAChB,KAAa,EACb,QAAoD,EACE,EAAE;IACxD,MAAM,OAAO,GAAG,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;IACnE,MAAM,QAAQ,GAAkB,EAAE,CAAC;IACnC,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,MAAM,GAAG,GAAG,cAAc,CAAC,QAAQ,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;QACpD,IAAI,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC;YAAE,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAC3D,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAC7B,CAAC;IACD,OAAO,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;AAClC,CAAC,CAAC;AAEF,8EAA8E;AAC9E,2EAA2E;AAC3E,2EAA2E;AAC3E,mBAAmB;AACnB,MAAM,CAAC,MAAM,sBAAsB,GAAG,CACpC,QAAgB,EAChB,MAAoF,EAC/C,EAAE;IACvC,KAAK,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,IAAI,MAAM,EAAE,CAAC;QACvC,MAAM,SAAS,GAAG,eAAe,CAC/B,QAAQ,EACR,KAAK,EACL,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,uBAAuB,CAAC,CACvF,CAAC;QACF,IAAI,MAAM,CAAC,SAAS,CAAC,SAAS,CAAC;YAAE,OAAO,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;IACzE,CAAC;IACD,OAAO,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;AACnC,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,SAAS,GAAG,CACvB,QAAoD,EAC7B,EAAE,CAAC,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AAEtF,yEAAyE;AACzE,8EAA8E;AAC9E,gEAAgE;AAChE,MAAM,mBAAmB,GAAG,qBAAqB,CAAC;AAElD,MAAM,UAAU,GAAG,CAAC,OAAe,EAAE,QAAyB,EAAU,EAAE,CACxE,OAAO,CAAC,UAAU,CAAC,aAAa,EAAE,CAAC,KAAK,EAAE,KAAa,EAAE,EAAE;IACzD,MAAM,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IACxC,OAAO,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,mBAAmB,EAAE,MAAM,CAAC,CAAC;AACtF,CAAC,CAAC,CAAC;AAEL,MAAM,WAAW,GAAG,IAAI,GAAG,EAAkB,CAAC;AAE9C,MAAM,cAAc,GAAG,CAAC,OAAe,EAAU,EAAE;IACjD,MAAM,MAAM,GAAG,WAAW,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IACxC,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,MAAM,CAAC;IACxC,MAAM,QAAQ,GAAG,IAAI,MAAM,CAAC,OAAO,CAAC,CAAC;IACrC,WAAW,CAAC,GAAG,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IACnC,OAAO,QAAQ,CAAC;AAClB,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,UAAU,GAAG,CACxB,QAA+B,EAC/B,QAAyB,EACzB,KAAa,EACJ,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,cAAc,CAAC,UAAU,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;AAOpG,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,IAAgB,EAAE,QAAgB,EAA0B,EAAE;IAC3F,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IACxE,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;QAChC,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACxC,IAAI,QAAQ,KAAK,IAAI;YAAE,OAAO,QAAQ,CAAC;IACzC,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC,CAAC;AAOF,MAAM,CAAC,MAAM,aAAa,GAAG,CAC3B,IAAc,EACd,QAAyB,EACzB,UAAkB,EACT,EAAE;IACX,IAAI,IAAI,CAAC,EAAE,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,EAAE,QAAQ,EAAE,UAAU,CAAC;QAAE,OAAO,KAAK,CAAC;IACnF,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,UAAU,CAAC,IAAI,CAAC,KAAK,EAAE,QAAQ,EAAE,UAAU,CAAC;QAAE,OAAO,KAAK,CAAC;IACxF,OAAO,IAAI,CAAC;AACd,CAAC,CAAC"}
|