-
Notifications
You must be signed in to change notification settings - Fork 0
/
prepublishSafe.ts
96 lines (75 loc) · 2.31 KB
/
prepublishSafe.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
/// <reference types="bun-types" />
import nodePath from 'path';
import type { PackageJson } from './packages/runmate/src';
export interface PackageItem {
index: number;
json: PackageJson;
dependents: string[];
}
class DepTree {
seen = new Map<string, PackageItem>();
packageValues: PackageItem[] = [];
packageByName = new Map<string, PackageItem>();
constructor(value: PackageJson[]) {
this.packageValues = value.map((json, index) => {
const item: PackageItem = {
json,
index,
dependents: [],
};
this.packageByName.set(json.name, item);
return item;
});
}
find = (): PackageItem[] => {
return (
this.packageValues
.map((el, index) => this.traverse(el, index))
// fixme if a package has only 1 dependent and this dependent is the first, it will break the pipeline
.sort((a, b) => b.dependents.length - a.dependents.length)
);
};
private traverse = (input: PackageItem, index: number): PackageItem => {
let { seen } = this;
const { name, dependencies, devDependencies, optionalDependencies, peerDependencies } = input.json;
let current = seen.get(name);
if (current) return current;
current = {
index,
json: input.json,
dependents: [],
};
seen.set(name, current);
const deps = {
...optionalDependencies,
...peerDependencies,
...devDependencies,
...dependencies,
};
const entries = Object.entries(deps);
for (let [depName] of entries) {
const localDep = this.packageByName.get(depName);
if (!localDep) continue;
const usedLocalDep = this.traverse(localDep, localDep.index);
usedLocalDep.dependents.push(name);
}
return current;
};
}
const packages = new Bun.Glob(
'./packages/**/package.json' //
).scanSync({ absolute: true, onlyFiles: false });
const jsons: PackageJson[] = [];
const pathByPackage = new Map<string, string>();
for (let path of packages) {
const file: PackageJson = await Bun.file(path).json();
jsons.push(file);
pathByPackage.set(file.name, nodePath.dirname(path));
}
const depTree = new DepTree(jsons).find();
await Bun.$`pnpm i`;
for (let dep of depTree) {
const cwd = pathByPackage.get(dep.json.name);
const shell = Bun.$.cwd(cwd);
await shell`pnpm run prepublishOnly`;
}