@goodbones/core 0.1.0-beta.3 → 0.1.0-beta.4
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/build/dts/core/graph.d.ts +1 -0
- package/build/dts/core/graph.d.ts.map +1 -1
- package/build/dts/index.d.ts +3 -2
- package/build/dts/index.d.ts.map +1 -1
- package/build/dts/infrastructure/walk.d.ts +6 -0
- package/build/dts/infrastructure/walk.d.ts.map +1 -1
- package/build/dts/manifest/infer.d.ts +55 -0
- package/build/dts/manifest/infer.d.ts.map +1 -0
- package/build/dts/ports/language.d.ts +2 -0
- package/build/dts/ports/language.d.ts.map +1 -1
- package/build/esm/core/graph.js +8 -0
- package/build/esm/core/graph.js.map +1 -1
- package/build/esm/index.js +3 -2
- package/build/esm/index.js.map +1 -1
- package/build/esm/infrastructure/walk.js +57 -1
- package/build/esm/infrastructure/walk.js.map +1 -1
- package/build/esm/manifest/infer.js +455 -0
- package/build/esm/manifest/infer.js.map +1 -0
- package/package.json +1 -1
- package/src/core/graph.ts +12 -0
- package/src/index.ts +20 -1
- package/src/infrastructure/walk.ts +70 -1
- package/src/manifest/infer.ts +643 -0
- package/src/ports/language.ts +11 -0
|
@@ -0,0 +1,455 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// Paths
|
|
3
|
+
const dirnameOf = (file) => {
|
|
4
|
+
const at = file.lastIndexOf("/");
|
|
5
|
+
return at === -1 ? "" : file.slice(0, at);
|
|
6
|
+
};
|
|
7
|
+
const basenameOf = (file) => file.slice(file.lastIndexOf("/") + 1);
|
|
8
|
+
// `folder` is `p` or an ancestor of it. The empty folder is every path's.
|
|
9
|
+
const isUnder = (p, folder) => folder === "" || p === folder || p.startsWith(`${folder}/`);
|
|
10
|
+
const depthBelow = (p, folder) => p === folder ? 0 : (folder === "" ? p : p.slice(folder.length + 1)).split("/").length;
|
|
11
|
+
const sorted = (items) => [...items].sort();
|
|
12
|
+
const memberOf = (p, generalize) => {
|
|
13
|
+
for (const group of generalize) {
|
|
14
|
+
for (const member of group.members) {
|
|
15
|
+
const folder = group.parent === "" ? member : `${group.parent}/${member}`;
|
|
16
|
+
if (isUnder(p, folder))
|
|
17
|
+
return { group, member };
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return null;
|
|
21
|
+
};
|
|
22
|
+
const capturedPathOf = (group) => group.parent === "" ? `{${group.capture}}` : `${group.parent}/{${group.capture}}`;
|
|
23
|
+
const rewrite = (p, generalize) => {
|
|
24
|
+
const membership = memberOf(p, generalize);
|
|
25
|
+
if (membership === null)
|
|
26
|
+
return p;
|
|
27
|
+
const { group, member } = membership;
|
|
28
|
+
const folder = group.parent === "" ? member : `${group.parent}/${member}`;
|
|
29
|
+
const captured = capturedPathOf(group);
|
|
30
|
+
return p === folder ? captured : `${captured}${p.slice(folder.length)}`;
|
|
31
|
+
};
|
|
32
|
+
const folderAt = (root, p) => {
|
|
33
|
+
if (p === root.path)
|
|
34
|
+
return root;
|
|
35
|
+
const rest = root.path === "" ? p : p.slice(root.path.length + 1);
|
|
36
|
+
let at = root;
|
|
37
|
+
for (const segment of rest.split("/")) {
|
|
38
|
+
const existing = at.children.get(segment);
|
|
39
|
+
if (existing !== undefined) {
|
|
40
|
+
at = existing;
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
const made = {
|
|
44
|
+
path: at.path === "" ? segment : `${at.path}/${segment}`,
|
|
45
|
+
name: segment,
|
|
46
|
+
files: [],
|
|
47
|
+
children: new Map(),
|
|
48
|
+
};
|
|
49
|
+
at.children.set(segment, made);
|
|
50
|
+
at = made;
|
|
51
|
+
}
|
|
52
|
+
return at;
|
|
53
|
+
};
|
|
54
|
+
const trieOf = (input, generalize) => {
|
|
55
|
+
const roots = input.roots.map((root) => ({
|
|
56
|
+
path: root,
|
|
57
|
+
name: basenameOf(root),
|
|
58
|
+
files: [],
|
|
59
|
+
children: new Map(),
|
|
60
|
+
}));
|
|
61
|
+
for (const file of input.files) {
|
|
62
|
+
const folder = rewrite(dirnameOf(file), generalize);
|
|
63
|
+
const root = roots.find((one) => isUnder(folder, one.path));
|
|
64
|
+
if (root === undefined)
|
|
65
|
+
continue;
|
|
66
|
+
folderAt(root, folder).files.push(file);
|
|
67
|
+
}
|
|
68
|
+
return roots;
|
|
69
|
+
};
|
|
70
|
+
const basesOf = (input, generalize) => {
|
|
71
|
+
const all = new Set(input.roots);
|
|
72
|
+
for (const one of input.packages) {
|
|
73
|
+
all.add(rewrite(one.root, generalize));
|
|
74
|
+
if (one.source !== null)
|
|
75
|
+
all.add(rewrite(one.source, generalize));
|
|
76
|
+
}
|
|
77
|
+
return { all: sorted(all) };
|
|
78
|
+
};
|
|
79
|
+
const baseOf = (folder, bases) => {
|
|
80
|
+
let best = null;
|
|
81
|
+
for (const base of bases.all) {
|
|
82
|
+
if (!isUnder(folder, base))
|
|
83
|
+
continue;
|
|
84
|
+
if (best === null || base.length > best.length)
|
|
85
|
+
best = base;
|
|
86
|
+
}
|
|
87
|
+
return best ?? "";
|
|
88
|
+
};
|
|
89
|
+
// A folder is a node when it is within `depth` of the base it counts from, or
|
|
90
|
+
// when it lies on the way to one — the folders between a walk root and a
|
|
91
|
+
// package are structure, and a node each whatever the depth.
|
|
92
|
+
const isNode = (folder, input, bases) => input.roots.includes(folder.path) ||
|
|
93
|
+
bases.all.some((base) => isUnder(base, folder.path)) ||
|
|
94
|
+
depthBelow(folder.path, baseOf(folder.path, bases)) <= input.depth;
|
|
95
|
+
const nodeOf = (folder, input, bases) => {
|
|
96
|
+
const node = {
|
|
97
|
+
path: folder.path,
|
|
98
|
+
key: `${folder.name}/`,
|
|
99
|
+
folder,
|
|
100
|
+
files: [...folder.files],
|
|
101
|
+
children: new Map(),
|
|
102
|
+
stray: false,
|
|
103
|
+
allow: new Set(),
|
|
104
|
+
external: new Set(),
|
|
105
|
+
edges: 0,
|
|
106
|
+
};
|
|
107
|
+
const absorb = (from) => {
|
|
108
|
+
for (const child of from.children.values()) {
|
|
109
|
+
if (isNode(child, input, bases)) {
|
|
110
|
+
node.children.set(child.name, nodeOf(child, input, bases));
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
node.stray = true;
|
|
114
|
+
for (const file of child.files)
|
|
115
|
+
node.files.push(file);
|
|
116
|
+
absorb(child);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
absorb(folder);
|
|
121
|
+
return node;
|
|
122
|
+
};
|
|
123
|
+
// The deepest node whose folder holds `p` (a rewritten path), or null when
|
|
124
|
+
// no walk root does.
|
|
125
|
+
const governorOf = (p, roots) => {
|
|
126
|
+
const root = roots.find((one) => isUnder(p, one.path));
|
|
127
|
+
if (root === undefined)
|
|
128
|
+
return null;
|
|
129
|
+
const descend = (at) => {
|
|
130
|
+
for (const child of at.children.values())
|
|
131
|
+
if (isUnder(p, child.path))
|
|
132
|
+
return descend(child);
|
|
133
|
+
return at;
|
|
134
|
+
};
|
|
135
|
+
return descend(root);
|
|
136
|
+
};
|
|
137
|
+
const eachNode = (roots, visit) => {
|
|
138
|
+
const walk = (node) => {
|
|
139
|
+
visit(node);
|
|
140
|
+
for (const child of node.children.values())
|
|
141
|
+
walk(child);
|
|
142
|
+
};
|
|
143
|
+
for (const root of roots)
|
|
144
|
+
walk(root);
|
|
145
|
+
};
|
|
146
|
+
// ---------------------------------------------------------------------------
|
|
147
|
+
// Allow sets.
|
|
148
|
+
// What a local target is written as: the node that governs it, as a glob. A
|
|
149
|
+
// file directly in a node that has children of its own is `node/*` — the
|
|
150
|
+
// layer's own files, such as a barrel, and not the tiers beneath — and
|
|
151
|
+
// anything else is `node/**`. A capture in that path survives only when the
|
|
152
|
+
// importer is in the same member; from anywhere else it is `*`.
|
|
153
|
+
const entryFor = (importer, target, roots, generalize) => {
|
|
154
|
+
const rewritten = rewrite(target, generalize);
|
|
155
|
+
const node = governorOf(rewritten, roots);
|
|
156
|
+
if (node === null)
|
|
157
|
+
return target;
|
|
158
|
+
const from = memberOf(importer, generalize);
|
|
159
|
+
const to = memberOf(target, generalize);
|
|
160
|
+
const sameGroup = from !== null &&
|
|
161
|
+
to !== null &&
|
|
162
|
+
from.group.parent === to.group.parent &&
|
|
163
|
+
from.group.capture === to.group.capture;
|
|
164
|
+
if (to !== null && sameGroup && to.member !== from.member) {
|
|
165
|
+
const reach = to.group.crossReach;
|
|
166
|
+
const folder = to.group.parent === "" ? to.member : `${to.group.parent}/${to.member}`;
|
|
167
|
+
if (reach !== null && target === `${folder}/${reach}`) {
|
|
168
|
+
return `${to.group.parent === "" ? "" : `${to.group.parent}/`}*/${reach}`;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
const direct = dirnameOf(rewritten) === node.path && node.children.size > 0;
|
|
172
|
+
const glob = `${node.path}/${direct ? "*" : "**"}`;
|
|
173
|
+
if (to === null)
|
|
174
|
+
return glob;
|
|
175
|
+
const sameMember = sameGroup && from.member === to.member;
|
|
176
|
+
return sameMember ? glob : glob.replace(`{${to.group.capture}}`, "*");
|
|
177
|
+
};
|
|
178
|
+
const fillAllowSets = (roots, input, generalize) => {
|
|
179
|
+
eachNode(roots, (node) => {
|
|
180
|
+
for (const file of node.files) {
|
|
181
|
+
for (const target of input.targetsOf(file)) {
|
|
182
|
+
node.edges += 1;
|
|
183
|
+
switch (target.kind) {
|
|
184
|
+
case "local":
|
|
185
|
+
node.allow.add(entryFor(file, target.path, roots, generalize));
|
|
186
|
+
break;
|
|
187
|
+
case "builtin":
|
|
188
|
+
node.allow.add(target.path);
|
|
189
|
+
break;
|
|
190
|
+
case "external":
|
|
191
|
+
node.external.add(target.package);
|
|
192
|
+
break;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
});
|
|
197
|
+
};
|
|
198
|
+
// ---------------------------------------------------------------------------
|
|
199
|
+
// Candidates: siblings that share a shape.
|
|
200
|
+
// `auth.module.ts` and `user.module.ts` are one kind of file; `index.ts` is
|
|
201
|
+
// its own. The first segment is the name, the rest is what it is.
|
|
202
|
+
const stereotypeOf = (file) => {
|
|
203
|
+
const parts = basenameOf(file).split(".");
|
|
204
|
+
return parts.length >= 3 ? `*.${parts.slice(1).join(".")}` : basenameOf(file);
|
|
205
|
+
};
|
|
206
|
+
const intersect = (a, b) => sorted([...a].filter((one) => b.has(one)));
|
|
207
|
+
const alike = (a, b) => {
|
|
208
|
+
if (intersect(a.folders, b.folders).length >= 2)
|
|
209
|
+
return true;
|
|
210
|
+
const union = new Set([...a.stereotypes, ...b.stereotypes]);
|
|
211
|
+
return union.size > 0 && intersect(a.stereotypes, b.stereotypes).length / union.size >= 0.5;
|
|
212
|
+
};
|
|
213
|
+
const shapeOf = (folder) => ({
|
|
214
|
+
folders: new Set(folder.children.keys()),
|
|
215
|
+
stereotypes: new Set(folder.files.map(stereotypeOf)),
|
|
216
|
+
});
|
|
217
|
+
// `modules` → `module`; `entities` → `entity`; `packages` → `package`. What a
|
|
218
|
+
// human would name the capture; anything unpronounceable is `name`.
|
|
219
|
+
export const singularOf = (plural) => {
|
|
220
|
+
const word = plural.replace(/[^A-Za-z0-9]/g, "");
|
|
221
|
+
const singular = /ies$/.test(word)
|
|
222
|
+
? word.replace(/ies$/, "y")
|
|
223
|
+
: /(ses|xes|zes|shes|ches)$/.test(word)
|
|
224
|
+
? word.slice(0, -2)
|
|
225
|
+
: /[^s]s$/.test(word)
|
|
226
|
+
? word.slice(0, -1)
|
|
227
|
+
: word;
|
|
228
|
+
return singular === "" || /^[0-9]/.test(singular) ? "name" : singular;
|
|
229
|
+
};
|
|
230
|
+
const groupsOf = (members) => {
|
|
231
|
+
const parent = new Map(members.map(([name]) => [name, name]));
|
|
232
|
+
const find = (name) => {
|
|
233
|
+
let at = name;
|
|
234
|
+
while ((parent.get(at) ?? at) !== at)
|
|
235
|
+
at = parent.get(at) ?? at;
|
|
236
|
+
return at;
|
|
237
|
+
};
|
|
238
|
+
for (const [i, [a, shapeA]] of members.entries()) {
|
|
239
|
+
for (const [b, shapeB] of members.slice(i + 1)) {
|
|
240
|
+
if (alike(shapeA, shapeB))
|
|
241
|
+
parent.set(find(a), find(b));
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
const groups = new Map();
|
|
245
|
+
for (const [name] of members) {
|
|
246
|
+
const key = find(name);
|
|
247
|
+
groups.set(key, [...(groups.get(key) ?? []), name]);
|
|
248
|
+
}
|
|
249
|
+
return [...groups.values()]
|
|
250
|
+
.filter((group) => group.length >= 2)
|
|
251
|
+
.map((group) => sorted(group))
|
|
252
|
+
.sort((a, b) => (a[0] ?? "").localeCompare(b[0] ?? ""));
|
|
253
|
+
};
|
|
254
|
+
// The sibling groups under every node of the tree as it stands with the
|
|
255
|
+
// generalizations already accepted — never inside one, since a generalized
|
|
256
|
+
// node's children are already a merge.
|
|
257
|
+
export const candidatesOf = (input, generalize = []) => {
|
|
258
|
+
const trie = trieOf(input, generalize);
|
|
259
|
+
const bases = basesOf(input, generalize);
|
|
260
|
+
const roots = trie.map((folder) => nodeOf(folder, input, bases));
|
|
261
|
+
const candidates = [];
|
|
262
|
+
eachNode(roots, (node) => {
|
|
263
|
+
if (node.path.includes("{") || node.children.size < 2)
|
|
264
|
+
return;
|
|
265
|
+
const members = sorted(node.children.keys()).flatMap((name) => {
|
|
266
|
+
const folder = node.folder.children.get(name);
|
|
267
|
+
return folder === undefined ? [] : [[name, shapeOf(folder)]];
|
|
268
|
+
});
|
|
269
|
+
const shapes = new Map(members);
|
|
270
|
+
const taken = new Set();
|
|
271
|
+
for (const group of groupsOf(members)) {
|
|
272
|
+
const shapesOfGroup = group.flatMap((name) => {
|
|
273
|
+
const shape = shapes.get(name);
|
|
274
|
+
return shape === undefined ? [] : [shape];
|
|
275
|
+
});
|
|
276
|
+
const sharedOf = (pick) => {
|
|
277
|
+
const [head, ...rest] = shapesOfGroup;
|
|
278
|
+
if (head === undefined)
|
|
279
|
+
return [];
|
|
280
|
+
return sorted(rest.reduce((acc, shape) => new Set(intersect(acc, pick(shape))), pick(head)));
|
|
281
|
+
};
|
|
282
|
+
const sharedFolders = sharedOf((shape) => shape.folders);
|
|
283
|
+
const sharedStereotypes = sharedOf((shape) => shape.stereotypes);
|
|
284
|
+
let capture = singularOf(node.folder.name);
|
|
285
|
+
for (let n = 2; taken.has(capture); n += 1)
|
|
286
|
+
capture = `${singularOf(node.folder.name)}${String(n)}`;
|
|
287
|
+
taken.add(capture);
|
|
288
|
+
// Edges between members, and whether they all land on one place.
|
|
289
|
+
const memberFolder = (name) => node.path === "" ? name : `${node.path}/${name}`;
|
|
290
|
+
const isIn = (p) => group.find((name) => isUnder(p, memberFolder(name))) ?? null;
|
|
291
|
+
let crossEdges = 0;
|
|
292
|
+
const landings = new Set();
|
|
293
|
+
for (const file of input.files) {
|
|
294
|
+
const from = isIn(file);
|
|
295
|
+
if (from === null)
|
|
296
|
+
continue;
|
|
297
|
+
for (const target of input.targetsOf(file)) {
|
|
298
|
+
if (target.kind !== "local")
|
|
299
|
+
continue;
|
|
300
|
+
const to = isIn(target.path);
|
|
301
|
+
if (to === null || to === from)
|
|
302
|
+
continue;
|
|
303
|
+
crossEdges += 1;
|
|
304
|
+
landings.add(target.path.slice(memberFolder(to).length + 1));
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
const [landing] = sorted(landings);
|
|
308
|
+
candidates.push({
|
|
309
|
+
parent: node.path,
|
|
310
|
+
members: group,
|
|
311
|
+
sharedFolders,
|
|
312
|
+
sharedStereotypes,
|
|
313
|
+
capture,
|
|
314
|
+
crossEdges,
|
|
315
|
+
crossReach: landings.size === 1 && landing !== undefined ? landing : null,
|
|
316
|
+
});
|
|
317
|
+
}
|
|
318
|
+
});
|
|
319
|
+
return candidates.sort((a, b) => {
|
|
320
|
+
const byParent = a.parent.localeCompare(b.parent);
|
|
321
|
+
return byParent !== 0 ? byParent : (a.members[0] ?? "").localeCompare(b.members[0] ?? "");
|
|
322
|
+
});
|
|
323
|
+
};
|
|
324
|
+
// ---------------------------------------------------------------------------
|
|
325
|
+
// Collapse: children that all reach the same things are one node.
|
|
326
|
+
const normalized = (node, under) => sorted(new Set([...node.allow].map((entry) => (isUnder(entry, under) ? `${under}/**` : entry))));
|
|
327
|
+
const sameList = (a, b) => a.length === b.length && a.every((one, index) => one === b[index]);
|
|
328
|
+
const collapse = (node) => {
|
|
329
|
+
for (const child of node.children.values())
|
|
330
|
+
collapse(child);
|
|
331
|
+
if (node.children.size === 0)
|
|
332
|
+
return;
|
|
333
|
+
const children = [...node.children.values()];
|
|
334
|
+
if (children.some((child) => child.children.size > 0))
|
|
335
|
+
return;
|
|
336
|
+
const [first] = children;
|
|
337
|
+
if (first === undefined)
|
|
338
|
+
return;
|
|
339
|
+
const shared = normalized(first, node.path);
|
|
340
|
+
const externals = sorted(first.external);
|
|
341
|
+
const agree = children.every((child) => sameList(normalized(child, node.path), shared) && sameList(sorted(child.external), externals));
|
|
342
|
+
if (!agree)
|
|
343
|
+
return;
|
|
344
|
+
const own = normalized(node, node.path);
|
|
345
|
+
if (!own.every((entry) => shared.includes(entry)))
|
|
346
|
+
return;
|
|
347
|
+
if (!sorted(node.external).every((entry) => externals.includes(entry)))
|
|
348
|
+
return;
|
|
349
|
+
node.allow = new Set(shared);
|
|
350
|
+
node.external = new Set(externals);
|
|
351
|
+
for (const child of children) {
|
|
352
|
+
for (const file of child.files)
|
|
353
|
+
node.files.push(file);
|
|
354
|
+
node.edges += child.edges;
|
|
355
|
+
}
|
|
356
|
+
node.children = new Map();
|
|
357
|
+
node.stray = true;
|
|
358
|
+
};
|
|
359
|
+
// ---------------------------------------------------------------------------
|
|
360
|
+
// Emitting.
|
|
361
|
+
const shortenWith = (aliases) => {
|
|
362
|
+
const entries = Object.entries(aliases).sort(([, a], [, b]) => b.length - a.length);
|
|
363
|
+
return (p) => {
|
|
364
|
+
for (const [alias, target] of entries) {
|
|
365
|
+
if (p === target)
|
|
366
|
+
return alias;
|
|
367
|
+
if (p.startsWith(`${target}/`))
|
|
368
|
+
return `${alias}${p.slice(target.length)}`;
|
|
369
|
+
}
|
|
370
|
+
return p;
|
|
371
|
+
};
|
|
372
|
+
};
|
|
373
|
+
const CATCH_ALL = "**/";
|
|
374
|
+
export const inferManifest = (input, options) => {
|
|
375
|
+
const { generalize } = options;
|
|
376
|
+
const trie = trieOf(input, generalize);
|
|
377
|
+
const bases = basesOf(input, generalize);
|
|
378
|
+
const roots = trie.map((folder) => nodeOf(folder, input, bases));
|
|
379
|
+
fillAllowSets(roots, input, generalize);
|
|
380
|
+
if (options.collapse)
|
|
381
|
+
for (const root of roots)
|
|
382
|
+
collapse(root);
|
|
383
|
+
const shorten = shortenWith(options.aliases ?? {});
|
|
384
|
+
let unrestricted = 0;
|
|
385
|
+
let nodes = 0;
|
|
386
|
+
let files = 0;
|
|
387
|
+
const describe = (node) => {
|
|
388
|
+
const membership = generalize.find((group) => capturedPathOf(group) === node.path);
|
|
389
|
+
const across = membership === undefined
|
|
390
|
+
? ""
|
|
391
|
+
: ` across ${String(membership.members.length)} ${basenameOf(membership.parent)} (${membership.members.join(", ")})`;
|
|
392
|
+
const count = (n, noun) => `${String(n)} ${noun}${n === 1 ? "" : "s"}`;
|
|
393
|
+
return node.files.length === 0
|
|
394
|
+
? `As built on ${options.date}: no files of its own.`
|
|
395
|
+
: `As built on ${options.date}${across}: ${count(node.files.length, "file")}, ${count(node.edges, "edge")}.`;
|
|
396
|
+
};
|
|
397
|
+
const emit = (node) => {
|
|
398
|
+
nodes += 1;
|
|
399
|
+
files += node.files.length;
|
|
400
|
+
const children = {};
|
|
401
|
+
for (const name of sorted(node.children.keys())) {
|
|
402
|
+
const child = node.children.get(name);
|
|
403
|
+
if (child !== undefined)
|
|
404
|
+
children[child.key] = emit(child);
|
|
405
|
+
}
|
|
406
|
+
if (node.stray)
|
|
407
|
+
children[CATCH_ALL] = { layout: "open", children: {} };
|
|
408
|
+
const imports = node.files.length === 0
|
|
409
|
+
? {}
|
|
410
|
+
: {
|
|
411
|
+
imports: {
|
|
412
|
+
message: `This import is not on the allowlist infer wrote for ${node.path}/ on ${options.date}. Add it by name if it belongs here.`,
|
|
413
|
+
unrestricted: true,
|
|
414
|
+
...(node.allow.size > 0 ? { allow: sorted([...node.allow].map(shorten)) } : {}),
|
|
415
|
+
...(node.external.size > 0 ? { external: sorted(node.external) } : {}),
|
|
416
|
+
},
|
|
417
|
+
};
|
|
418
|
+
if (node.files.length > 0)
|
|
419
|
+
unrestricted += 1;
|
|
420
|
+
return {
|
|
421
|
+
message: describe(node),
|
|
422
|
+
layout: "open",
|
|
423
|
+
...imports,
|
|
424
|
+
children,
|
|
425
|
+
};
|
|
426
|
+
};
|
|
427
|
+
const tree = {};
|
|
428
|
+
for (const root of roots)
|
|
429
|
+
tree[`${shorten(root.path)}/`] = emit(root);
|
|
430
|
+
const within = input.roots.map((root) => shorten(`${root}/**`));
|
|
431
|
+
const manifest = {
|
|
432
|
+
resolve: options.resolve,
|
|
433
|
+
baseline: options.baseline,
|
|
434
|
+
...(options.aliases === undefined || Object.keys(options.aliases).length === 0
|
|
435
|
+
? {}
|
|
436
|
+
: { aliases: options.aliases }),
|
|
437
|
+
limits: { unrestricted, partial: 0 },
|
|
438
|
+
...(options.hasCycles
|
|
439
|
+
? {}
|
|
440
|
+
: {
|
|
441
|
+
graph: {
|
|
442
|
+
cycles: [
|
|
443
|
+
{
|
|
444
|
+
name: "no-cycles",
|
|
445
|
+
message: "These files import each other, directly or through others. The tree had no cycle when this manifest was inferred; keep it that way.",
|
|
446
|
+
within: within.length === 1 ? (within[0] ?? "") : within,
|
|
447
|
+
},
|
|
448
|
+
],
|
|
449
|
+
},
|
|
450
|
+
}),
|
|
451
|
+
tree,
|
|
452
|
+
};
|
|
453
|
+
return { manifest, nodes, files };
|
|
454
|
+
};
|
|
455
|
+
//# sourceMappingURL=infer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"infer.js","sourceRoot":"","sources":["../../../src/manifest/infer.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@goodbones/core",
|
|
3
|
-
"version": "0.1.0-beta.
|
|
3
|
+
"version": "0.1.0-beta.4",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"description": "Architecture policy as one manifest of your repository, language-agnostic: the manifest schema, the evaluators for imports, exports, members, surface, structure and the import graph, the ports a language pack implements, and the loader that turns a manifest into a policy every rule of which has proven it can fire.",
|
package/src/core/graph.ts
CHANGED
|
@@ -215,6 +215,18 @@ const stronglyConnected = (
|
|
|
215
215
|
return components;
|
|
216
216
|
};
|
|
217
217
|
|
|
218
|
+
// Every cycle in the graph, each as its sorted member set. What `infer` asks
|
|
219
|
+
// before it writes a no-cycles rule: a rule the tree fails on day one is a
|
|
220
|
+
// baseline entry, not a description of the tree.
|
|
221
|
+
export const cyclesIn = (graph: Graph): ReadonlyArray<ReadonlyArray<string>> =>
|
|
222
|
+
stronglyConnected(graph.files, graph).filter((component) => {
|
|
223
|
+
const [first] = component;
|
|
224
|
+
return (
|
|
225
|
+
first !== undefined &&
|
|
226
|
+
(component.length > 1 || (graph.edges.get(first) ?? []).includes(first))
|
|
227
|
+
);
|
|
228
|
+
});
|
|
229
|
+
|
|
218
230
|
const evaluateCycles = (rule: CompiledGraphCycleRule, graph: Graph): ReadonlyArray<Violation> => {
|
|
219
231
|
const nodes = graph.files.filter((file) => inScope(rule, file));
|
|
220
232
|
const violations: Array<Violation> = [];
|
package/src/index.ts
CHANGED
|
@@ -37,6 +37,7 @@ export {
|
|
|
37
37
|
export {
|
|
38
38
|
type CompiledGraph,
|
|
39
39
|
compileGraphRules,
|
|
40
|
+
cyclesIn,
|
|
40
41
|
EMPTY_GRAPH_RULES,
|
|
41
42
|
evaluateGraph,
|
|
42
43
|
type Graph,
|
|
@@ -134,7 +135,13 @@ export {
|
|
|
134
135
|
type IncludeReader,
|
|
135
136
|
type SourceDocument,
|
|
136
137
|
} from "./infrastructure/manifest-include.js";
|
|
137
|
-
export {
|
|
138
|
+
export {
|
|
139
|
+
listPackageRoots,
|
|
140
|
+
listSourceFiles,
|
|
141
|
+
type PackagedLanguage,
|
|
142
|
+
type PackageRoot,
|
|
143
|
+
type WalkedLanguage,
|
|
144
|
+
} from "./infrastructure/walk.js";
|
|
138
145
|
export { type LoadedPolicy, loadPolicy, type LoadPolicyInput } from "./load/policy.js";
|
|
139
146
|
export { type LoweredRules, lowerManifest, type ProbeLanguage } from "./manifest/compile.js";
|
|
140
147
|
export {
|
|
@@ -145,6 +152,18 @@ export {
|
|
|
145
152
|
originOf,
|
|
146
153
|
type Substitution,
|
|
147
154
|
} from "./manifest/expand.js";
|
|
155
|
+
export {
|
|
156
|
+
type Candidate,
|
|
157
|
+
candidatesOf,
|
|
158
|
+
type Generalization,
|
|
159
|
+
type InferInput,
|
|
160
|
+
inferManifest,
|
|
161
|
+
type InferOptions,
|
|
162
|
+
type InferPackage,
|
|
163
|
+
type Inferred,
|
|
164
|
+
type InferredTarget,
|
|
165
|
+
singularOf,
|
|
166
|
+
} from "./manifest/infer.js";
|
|
148
167
|
export {
|
|
149
168
|
MANIFEST_NODE_SCHEMA_ID,
|
|
150
169
|
MANIFEST_SCHEMA_ID,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { readdirSync, statSync } from "node:fs";
|
|
1
|
+
import { existsSync, readdirSync, statSync } from "node:fs";
|
|
2
2
|
import * as path from "node:path";
|
|
3
3
|
|
|
4
4
|
import type { Language } from "../ports/language.js";
|
|
@@ -52,3 +52,72 @@ export const listSourceFiles = (
|
|
|
52
52
|
}
|
|
53
53
|
return found.sort();
|
|
54
54
|
};
|
|
55
|
+
|
|
56
|
+
// What `infer` needs to know about a language beyond the walker's two: what
|
|
57
|
+
// marks a package of it, and where a package keeps its source.
|
|
58
|
+
export type PackagedLanguage = Pick<Language, "packageMarkers" | "sourceRoots">;
|
|
59
|
+
|
|
60
|
+
export type PackageRoot = {
|
|
61
|
+
// Repo-relative folder with forward slashes; `""` is the repository itself.
|
|
62
|
+
readonly root: string;
|
|
63
|
+
// The package's source folder, repo-relative, when one of the language's
|
|
64
|
+
// `sourceRoots` exists under it; otherwise `null`, and source sits at the root.
|
|
65
|
+
readonly source: string | null;
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
// The packages under (and above) `roots`: every folder holding one of the
|
|
69
|
+
// languages' marker files, the walk roots' own ancestors included, so a walk
|
|
70
|
+
// rooted at `src/` still finds the `package.json` beside it. Sorted by path.
|
|
71
|
+
export const listPackageRoots = (
|
|
72
|
+
repoRoot: string,
|
|
73
|
+
roots: ReadonlyArray<string>,
|
|
74
|
+
languages: ReadonlyArray<PackagedLanguage>,
|
|
75
|
+
): ReadonlyArray<PackageRoot> => {
|
|
76
|
+
const markers = languages.flatMap((language) => language.packageMarkers);
|
|
77
|
+
const sourceRoots = languages.flatMap((language) => language.sourceRoots);
|
|
78
|
+
if (markers.length === 0) return [];
|
|
79
|
+
|
|
80
|
+
const isDirectory = (absolute: string): boolean => {
|
|
81
|
+
try {
|
|
82
|
+
return statSync(absolute).isDirectory();
|
|
83
|
+
} catch {
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
const relative = (absolute: string): string =>
|
|
88
|
+
path.relative(repoRoot, absolute).replaceAll(path.sep, "/");
|
|
89
|
+
|
|
90
|
+
const found = new Map<string, PackageRoot>();
|
|
91
|
+
const consider = (absolute: string): void => {
|
|
92
|
+
const key = relative(absolute);
|
|
93
|
+
if (found.has(key)) return;
|
|
94
|
+
if (!markers.some((marker) => existsSync(path.join(absolute, marker)))) return;
|
|
95
|
+
const source = sourceRoots.find((name) => isDirectory(path.join(absolute, name)));
|
|
96
|
+
found.set(key, {
|
|
97
|
+
root: key,
|
|
98
|
+
source: source === undefined ? null : relative(path.join(absolute, source)),
|
|
99
|
+
});
|
|
100
|
+
};
|
|
101
|
+
const walk = (absolute: string): void => {
|
|
102
|
+
consider(absolute);
|
|
103
|
+
for (const entry of readdirSync(absolute)) {
|
|
104
|
+
if (SKIPPED.has(entry)) continue;
|
|
105
|
+
const child = path.join(absolute, entry);
|
|
106
|
+
if (isDirectory(child)) walk(child);
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
const top = path.resolve(repoRoot);
|
|
111
|
+
for (const root of roots) {
|
|
112
|
+
let absolute = path.resolve(repoRoot, root);
|
|
113
|
+
if (!isDirectory(absolute)) absolute = path.dirname(absolute);
|
|
114
|
+
walk(absolute);
|
|
115
|
+
// The ancestors, up to the repository: a package is as often above the
|
|
116
|
+
// walk root as inside it.
|
|
117
|
+
for (let above = absolute; above.startsWith(top); above = path.dirname(above)) {
|
|
118
|
+
consider(above);
|
|
119
|
+
if (above === top) break;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return [...found.values()].sort((a, b) => a.root.localeCompare(b.root));
|
|
123
|
+
};
|