@monorepolint/utils 0.6.0-alpha.2 → 0.6.0-alpha.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/.turbo/turbo-clean.log +1 -1
- package/.turbo/turbo-compile-typescript.log +1 -1
- package/.turbo/turbo-lint.log +7 -7
- package/.turbo/turbo-test.log +11 -10
- package/.turbo/turbo-transpile-typescript.log +4 -4
- package/CHANGELOG.md +4 -0
- package/build/js/index.js +489 -443
- package/build/js/index.js.map +1 -1
- package/build/tsconfig.tsbuildinfo +1 -1
- package/build/types/CachingHost.d.ts.map +1 -1
- package/build/types/Host.d.ts.map +1 -1
- package/build/types/PackageJson.d.ts.map +1 -1
- package/build/types/SimpleHost.d.ts.map +1 -1
- package/build/types/Table.d.ts.map +1 -1
- package/build/types/findWorkspaceDir.d.ts.map +1 -1
- package/build/types/getPackageNameToDir.d.ts.map +1 -1
- package/build/types/getWorkspacePackageDirs.d.ts.map +1 -1
- package/build/types/index.d.ts +7 -7
- package/build/types/index.d.ts.map +1 -1
- package/build/types/matchesAnyGlob.d.ts.map +1 -1
- package/build/types/mutateJson.d.ts.map +1 -1
- package/build/types/nanosecondsToSanity.d.ts.map +1 -1
- package/coverage/AggregateTiming.ts.html +2 -2
- package/coverage/CachingHost.ts.html +252 -42
- package/coverage/Host.ts.html +15 -3
- package/coverage/PackageJson.ts.html +4 -4
- package/coverage/SimpleHost.ts.html +40 -7
- package/coverage/Table.ts.html +137 -29
- package/coverage/Timing.ts.html +1 -1
- package/coverage/clover.xml +527 -396
- package/coverage/coverage-final.json +13 -13
- package/coverage/findWorkspaceDir.ts.html +4 -4
- package/coverage/getPackageNameToDir.ts.html +18 -6
- package/coverage/getWorkspacePackageDirs.ts.html +168 -138
- package/coverage/index.html +40 -40
- package/coverage/index.ts.html +30 -30
- package/coverage/matchesAnyGlob.ts.html +37 -10
- package/coverage/mutateJson.ts.html +17 -5
- package/coverage/nanosecondsToSanity.ts.html +11 -5
- package/package.json +1 -2
- package/src/AggregateTiming.ts +1 -1
- package/src/CachingHost.ts +104 -34
- package/src/Host.ts +5 -1
- package/src/PackageJson.ts +3 -3
- package/src/SimpleHost.ts +14 -3
- package/src/Table.ts +58 -22
- package/src/__tests__/CachingHost.spec.ts +203 -166
- package/src/findWorkspaceDir.ts +3 -3
- package/src/getPackageNameToDir.ts +6 -2
- package/src/getWorkspacePackageDirs.ts +19 -9
- package/src/index.ts +7 -7
- package/src/matchesAnyGlob.ts +12 -3
- package/src/mutateJson.ts +5 -1
- package/src/nanosecondsToSanity.ts +3 -1
- package/vitest.config.mjs +6 -7
- package/vitest.config.mjs.timestamp-1736878329730-aa478e2241542.mjs +2 -2
package/build/js/index.js
CHANGED
|
@@ -1,149 +1,289 @@
|
|
|
1
|
-
// src/
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
import * as path from "node:path";
|
|
5
|
-
import * as fs from "node:fs";
|
|
6
|
-
import readYamlFile from "read-yaml-file";
|
|
7
|
-
import { findPackages } from "find-packages";
|
|
8
|
-
async function findPNPMWorkspacePackages(workspaceRoot) {
|
|
9
|
-
workspaceRoot = fs.realpathSync(workspaceRoot);
|
|
10
|
-
const workspaceManifest = await readYamlFile.default(
|
|
11
|
-
path.join(workspaceRoot, "pnpm-workspace.yaml")
|
|
12
|
-
);
|
|
13
|
-
return findPackages(workspaceRoot, {
|
|
14
|
-
ignore: ["**/node_modules/**", "**/bower_components/**"],
|
|
15
|
-
includeRoot: true,
|
|
16
|
-
patterns: workspaceManifest.packages
|
|
17
|
-
});
|
|
1
|
+
// src/nanosecondsToSanity.ts
|
|
2
|
+
function nanosecondsToSanity(n, precision = 9) {
|
|
3
|
+
return n / BigInt(1e9) + "." + ("" + n % BigInt(1e9)).padStart(9, "0").substring(0, precision) + "s";
|
|
18
4
|
}
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
5
|
+
|
|
6
|
+
// src/Table.ts
|
|
7
|
+
var Table = class {
|
|
8
|
+
#rows = [];
|
|
9
|
+
#config;
|
|
10
|
+
#columnWidths = [];
|
|
11
|
+
#footer = [];
|
|
12
|
+
#footerRowConfig;
|
|
13
|
+
#totalWidth = 0;
|
|
14
|
+
constructor(config) {
|
|
15
|
+
this.#config = {
|
|
16
|
+
padding: 2,
|
|
17
|
+
...config
|
|
18
|
+
};
|
|
19
|
+
this.#columnWidths.fill(0, 0, config.columns.length);
|
|
20
|
+
if (config.showFooter) {
|
|
21
|
+
this.#footerRowConfig = [];
|
|
22
|
+
for (const columnConfig of config.columns) {
|
|
23
|
+
if (columnConfig.footer === void 0) {
|
|
24
|
+
throw new Error("Must specify footer fields when showFooter is true");
|
|
25
|
+
} else if (typeof columnConfig.footer === "string") {
|
|
26
|
+
this.#footerRowConfig.push({
|
|
27
|
+
type: "string",
|
|
28
|
+
alignment: "left",
|
|
29
|
+
aggregate: "static",
|
|
30
|
+
value: columnConfig.footer
|
|
31
|
+
});
|
|
32
|
+
} else if ("value" in columnConfig.footer) {
|
|
33
|
+
this.#footerRowConfig.push({
|
|
34
|
+
type: "string",
|
|
35
|
+
alignment: "left",
|
|
36
|
+
...columnConfig.footer
|
|
37
|
+
});
|
|
38
|
+
} else if ("aggregate" in columnConfig.footer) {
|
|
39
|
+
if (columnConfig.type !== "bigint") {
|
|
40
|
+
throw new Error("expecting bigint for aggregate");
|
|
41
|
+
}
|
|
42
|
+
this.#footerRowConfig.push({
|
|
43
|
+
type: columnConfig.type,
|
|
44
|
+
renderAs: columnConfig.renderAs,
|
|
45
|
+
precision: columnConfig.precision,
|
|
46
|
+
alignment: "right",
|
|
47
|
+
...columnConfig.footer
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
}
|
|
26
51
|
}
|
|
27
|
-
return workspacePackages.map((project) => project.dir).filter((d) => d !== workspaceDir);
|
|
28
52
|
}
|
|
29
|
-
|
|
30
|
-
|
|
53
|
+
addRow(...data) {
|
|
54
|
+
this.#rows.push(data);
|
|
31
55
|
}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
56
|
+
#sumColumn(c) {
|
|
57
|
+
let total = BigInt(0);
|
|
58
|
+
for (const row of this.#rows) {
|
|
59
|
+
total += row[c];
|
|
60
|
+
}
|
|
61
|
+
return total;
|
|
62
|
+
}
|
|
63
|
+
#updateFooterRow() {
|
|
64
|
+
const footerRowConfig = this.#footerRowConfig;
|
|
65
|
+
if (footerRowConfig) {
|
|
66
|
+
for (let c = 0; c < footerRowConfig.length; c++) {
|
|
67
|
+
const footerColConfig = footerRowConfig[c];
|
|
68
|
+
switch (footerColConfig.aggregate) {
|
|
69
|
+
case "sum":
|
|
70
|
+
this.#footer[c] = this.#sumColumn(c);
|
|
71
|
+
break;
|
|
72
|
+
case "average":
|
|
73
|
+
this.#footer[c] = this.#sumColumn(c) / BigInt(this.#rows.length);
|
|
74
|
+
break;
|
|
75
|
+
case "static":
|
|
76
|
+
this.#footer[c] = footerColConfig.value;
|
|
77
|
+
break;
|
|
42
78
|
}
|
|
43
79
|
}
|
|
44
80
|
}
|
|
45
81
|
}
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
}
|
|
66
|
-
async function findWorkspaceDir(host, dir) {
|
|
67
|
-
const maybePnpmWorkspaceDir = await findPnpmWorkspaceDir(dir);
|
|
68
|
-
if (maybePnpmWorkspaceDir != null) {
|
|
69
|
-
return maybePnpmWorkspaceDir;
|
|
82
|
+
#calculateColumnWidths() {
|
|
83
|
+
var _a;
|
|
84
|
+
this.#columnWidths.fill(0, 0, this.#config.columns.length);
|
|
85
|
+
for (let c = 0; c < this.#config.columns.length; c++) {
|
|
86
|
+
const colConfig = this.#config.columns[c];
|
|
87
|
+
this.#columnWidths[c] = Math.max(
|
|
88
|
+
(this.#config.columns[c].header ?? "").length,
|
|
89
|
+
...this.#rows.map((a) => this.#getCellValueAsString(a[c], colConfig).length),
|
|
90
|
+
this.#footer && this.#footerRowConfig ? this.#getCellValueAsString(
|
|
91
|
+
((_a = this.#footer) == null ? void 0 : _a[c]) ?? "",
|
|
92
|
+
this.#footerRowConfig[c]
|
|
93
|
+
).length : 0
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
this.#totalWidth = 0;
|
|
97
|
+
for (const colWidth of this.#columnWidths) {
|
|
98
|
+
this.#totalWidth += colWidth;
|
|
99
|
+
}
|
|
100
|
+
this.#totalWidth += (this.#columnWidths.length - 1) * this.#config.padding;
|
|
70
101
|
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
102
|
+
#printSeparator(fillString) {
|
|
103
|
+
const paddingString = "".padStart(this.#config.padding, " ");
|
|
104
|
+
let hr2 = "";
|
|
105
|
+
for (let c = 0; c < this.#columnWidths.length; c++) {
|
|
106
|
+
hr2 += "".padStart(this.#columnWidths[c], fillString) + paddingString;
|
|
107
|
+
}
|
|
108
|
+
hr2 = hr2.trimRight();
|
|
109
|
+
console.log(hr2);
|
|
110
|
+
}
|
|
111
|
+
#printHeaderRow() {
|
|
112
|
+
if (this.#config.showHeader) {
|
|
113
|
+
const colConfigs = this.#config.columns;
|
|
114
|
+
const paddingString = "".padStart(this.#config.padding, " ");
|
|
115
|
+
let hr = "";
|
|
116
|
+
for (let c = 0; c < colConfigs.length; c++) {
|
|
117
|
+
const heading = colConfigs[c].header ?? "";
|
|
118
|
+
hr += heading.padEnd(this.#columnWidths[c], " ") + paddingString;
|
|
119
|
+
}
|
|
120
|
+
hr = hr.trimRight();
|
|
121
|
+
console.log(hr);
|
|
122
|
+
this.#printSeparator("-");
|
|
76
123
|
}
|
|
77
124
|
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
125
|
+
#printFooterRow() {
|
|
126
|
+
const footerRow = this.#footer;
|
|
127
|
+
if (footerRow) {
|
|
128
|
+
this.#printSeparator("=");
|
|
129
|
+
const paddingString = "".padStart(this.#config.padding, " ");
|
|
130
|
+
let hr = "";
|
|
131
|
+
for (let c = 0; c < footerRow.length; c++) {
|
|
132
|
+
hr += this.#getCellValueAligned(footerRow[c], this.#footerRowConfig[c], c) + paddingString;
|
|
133
|
+
}
|
|
134
|
+
hr = hr.trimRight();
|
|
135
|
+
console.log(hr);
|
|
136
|
+
}
|
|
81
137
|
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
// src/getPackageNameToDir.ts
|
|
86
|
-
import { join as pathJoin } from "path";
|
|
87
|
-
async function getPackageNameToDir(host, workspaceDir, resolvePaths = false) {
|
|
88
|
-
const ret = /* @__PURE__ */ new Map();
|
|
89
|
-
const workspacePackages = await getWorkspacePackageDirs(host, workspaceDir, resolvePaths);
|
|
90
|
-
for (const packageDir of workspacePackages) {
|
|
91
|
-
const packagePath = pathJoin(packageDir, "package.json");
|
|
92
|
-
const { name } = host.readJson(packagePath);
|
|
93
|
-
if (name === void 0) {
|
|
94
|
-
throw new Error(`Package needs a name: ${packagePath}`);
|
|
138
|
+
print() {
|
|
139
|
+
if (this.#config.sortColumn !== void 0) {
|
|
95
140
|
}
|
|
96
|
-
|
|
141
|
+
this.#updateFooterRow();
|
|
142
|
+
this.#calculateColumnWidths();
|
|
143
|
+
console.log();
|
|
144
|
+
console.log(`${this.#config.title}`);
|
|
145
|
+
console.log("".padStart(this.#totalWidth, "="));
|
|
146
|
+
const paddingString = "".padStart(this.#config.padding, " ");
|
|
147
|
+
if (this.#config.showHeader) {
|
|
148
|
+
this.#printHeaderRow();
|
|
149
|
+
}
|
|
150
|
+
for (let r = 0; r < this.#rows.length; r++) {
|
|
151
|
+
let rowText = "";
|
|
152
|
+
for (let c = 0; c < this.#config.columns.length; c++) {
|
|
153
|
+
rowText += this.getEntryAsStringAligned(c, r) + paddingString;
|
|
154
|
+
}
|
|
155
|
+
rowText.trim();
|
|
156
|
+
console.log(rowText);
|
|
157
|
+
}
|
|
158
|
+
if (this.#config.showFooter) this.#printFooterRow();
|
|
159
|
+
console.log();
|
|
97
160
|
}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
constructor(fs3 = realFs) {
|
|
105
|
-
this.fs = fs3;
|
|
161
|
+
#getCellValueAsString(value, config) {
|
|
162
|
+
if (config.type === "bigint" && config.renderAs === "nanoseconds") {
|
|
163
|
+
return nanosecondsToSanity(value, config.precision ?? 9);
|
|
164
|
+
} else {
|
|
165
|
+
return "" + value;
|
|
166
|
+
}
|
|
106
167
|
}
|
|
107
|
-
|
|
108
|
-
|
|
168
|
+
#getCellValueAligned(value, config, column) {
|
|
169
|
+
let result;
|
|
170
|
+
if (config.type === "bigint" && config.renderAs === "nanoseconds") {
|
|
171
|
+
result = nanosecondsToSanity(value, config.precision ?? 9);
|
|
172
|
+
} else {
|
|
173
|
+
result = "" + value;
|
|
174
|
+
}
|
|
175
|
+
if (config.alignment === "left") {
|
|
176
|
+
return result.padEnd(this.#columnWidths[column]);
|
|
177
|
+
} else {
|
|
178
|
+
return result.padStart(this.#columnWidths[column]);
|
|
179
|
+
}
|
|
109
180
|
}
|
|
110
|
-
|
|
111
|
-
this.
|
|
181
|
+
getEntryAsString(colNum, rowNum) {
|
|
182
|
+
const config = this.#config.columns[colNum];
|
|
183
|
+
if (config.type === "bigint" && config.renderAs === "nanoseconds") {
|
|
184
|
+
return nanosecondsToSanity(
|
|
185
|
+
this.#rows[rowNum][colNum],
|
|
186
|
+
config.precision ?? 9
|
|
187
|
+
);
|
|
188
|
+
} else {
|
|
189
|
+
return "" + this.#rows[rowNum][colNum];
|
|
190
|
+
}
|
|
112
191
|
}
|
|
113
|
-
|
|
114
|
-
|
|
192
|
+
getEntryAsStringAligned(colNum, rowNum) {
|
|
193
|
+
const config = this.#config.columns[colNum];
|
|
194
|
+
let result;
|
|
195
|
+
if (config.type === "bigint" && config.renderAs === "nanoseconds") {
|
|
196
|
+
result = nanosecondsToSanity(
|
|
197
|
+
this.#rows[rowNum][colNum],
|
|
198
|
+
config.precision ?? 9
|
|
199
|
+
);
|
|
200
|
+
} else {
|
|
201
|
+
result = "" + this.#rows[rowNum][colNum];
|
|
202
|
+
}
|
|
203
|
+
if (config.alignment === "left") {
|
|
204
|
+
return result.padEnd(this.#columnWidths[colNum]);
|
|
205
|
+
} else {
|
|
206
|
+
return result.padStart(this.#columnWidths[colNum]);
|
|
207
|
+
}
|
|
115
208
|
}
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
209
|
+
getColumnWidth(colNum, config) {
|
|
210
|
+
let maxWidth = Math.max(
|
|
211
|
+
(config.header ?? "").length,
|
|
212
|
+
this.#footer && this.#footerRowConfig ? this.#getCellValueAsString(
|
|
213
|
+
this.#footer[colNum],
|
|
214
|
+
this.#footerRowConfig[colNum]
|
|
215
|
+
).length : 0
|
|
216
|
+
);
|
|
217
|
+
for (let r = 0; r < this.#rows.length; r++) {
|
|
218
|
+
maxWidth = Math.max(maxWidth, this.getEntryAsString(colNum, r).length);
|
|
219
|
+
}
|
|
220
|
+
return maxWidth;
|
|
221
|
+
}
|
|
222
|
+
};
|
|
223
|
+
|
|
224
|
+
// src/AggregateTiming.ts
|
|
225
|
+
var AggregateTiming = class {
|
|
226
|
+
constructor(title) {
|
|
227
|
+
this.title = title;
|
|
228
|
+
}
|
|
229
|
+
#data = /* @__PURE__ */ new Map();
|
|
230
|
+
#last;
|
|
231
|
+
start(name) {
|
|
232
|
+
const time = process.hrtime.bigint();
|
|
233
|
+
if (this.#last) {
|
|
234
|
+
this.#last.total += time;
|
|
235
|
+
}
|
|
236
|
+
let data = this.#data.get(name);
|
|
237
|
+
if (data === void 0) {
|
|
238
|
+
data = { count: 1, total: -time };
|
|
239
|
+
this.#data.set(name, data);
|
|
119
240
|
} else {
|
|
120
|
-
|
|
241
|
+
data.total -= time;
|
|
242
|
+
data.count++;
|
|
121
243
|
}
|
|
244
|
+
this.#last = data;
|
|
122
245
|
}
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
246
|
+
stop() {
|
|
247
|
+
const time = process.hrtime.bigint();
|
|
248
|
+
if (this.#last) {
|
|
249
|
+
this.#last.total += time;
|
|
250
|
+
this.#last = void 0;
|
|
126
251
|
}
|
|
127
|
-
return this.fs.readFileSync(path4, opts == null ? void 0 : opts.encoding);
|
|
128
|
-
}
|
|
129
|
-
deleteFile(path4) {
|
|
130
|
-
this.fs.unlinkSync(path4);
|
|
131
|
-
}
|
|
132
|
-
readJson(filename) {
|
|
133
|
-
const contents = this.fs.readFileSync(filename, "utf-8");
|
|
134
|
-
return JSON.parse(contents);
|
|
135
|
-
}
|
|
136
|
-
writeJson(path4, o) {
|
|
137
|
-
return this.fs.writeFileSync(path4, JSON.stringify(o, void 0, 2) + "\n");
|
|
138
252
|
}
|
|
139
|
-
|
|
140
|
-
|
|
253
|
+
printResults() {
|
|
254
|
+
const table = new Table({
|
|
255
|
+
sortColumn: -1,
|
|
256
|
+
showFooter: true,
|
|
257
|
+
showHeader: true,
|
|
258
|
+
title: this.title,
|
|
259
|
+
columns: [
|
|
260
|
+
{
|
|
261
|
+
header: "Duration",
|
|
262
|
+
type: "bigint",
|
|
263
|
+
renderAs: "nanoseconds",
|
|
264
|
+
footer: { aggregate: "sum" }
|
|
265
|
+
},
|
|
266
|
+
{ header: "Task", type: "string", alignment: "left", footer: "TOTAL" },
|
|
267
|
+
{ header: "Count", type: "bigint", footer: { aggregate: "sum" } },
|
|
268
|
+
{ header: "Avg", type: "bigint", footer: { aggregate: "average" } }
|
|
269
|
+
]
|
|
270
|
+
});
|
|
271
|
+
for (const [name, value] of this.#data) {
|
|
272
|
+
table.addRow(
|
|
273
|
+
value.total,
|
|
274
|
+
name,
|
|
275
|
+
BigInt(value.count),
|
|
276
|
+
// fixme this can be a number later
|
|
277
|
+
value.total / BigInt(value.count)
|
|
278
|
+
);
|
|
279
|
+
}
|
|
280
|
+
table.print();
|
|
141
281
|
}
|
|
142
282
|
};
|
|
143
283
|
|
|
144
284
|
// src/CachingHost.ts
|
|
145
|
-
import * as
|
|
146
|
-
import * as
|
|
285
|
+
import * as realFs from "node:fs";
|
|
286
|
+
import * as path from "node:path";
|
|
147
287
|
function assertNoTombstone(node) {
|
|
148
288
|
if (node.tombstone) {
|
|
149
289
|
throw new Error(`Unexpected tombstone ${JSON.stringify(node)}`);
|
|
@@ -170,7 +310,7 @@ function assertHasParent(node) {
|
|
|
170
310
|
}
|
|
171
311
|
}
|
|
172
312
|
var CachingHost = class {
|
|
173
|
-
constructor(fs3 =
|
|
313
|
+
constructor(fs3 = realFs) {
|
|
174
314
|
this.fs = fs3;
|
|
175
315
|
}
|
|
176
316
|
// We need many trees because of windows, key is the `root`
|
|
@@ -183,19 +323,21 @@ var CachingHost = class {
|
|
|
183
323
|
parent: node.parent,
|
|
184
324
|
dir: node.dir
|
|
185
325
|
};
|
|
186
|
-
node.parent.dir.set(
|
|
326
|
+
node.parent.dir.set(path.basename(node.fullPath), newNode);
|
|
187
327
|
return newNode;
|
|
188
328
|
}
|
|
189
329
|
#unstubDirectory(node) {
|
|
190
330
|
for (const child of this.fs.readdirSync(node.fullPath)) {
|
|
191
|
-
this.#getNode(
|
|
331
|
+
this.#getNode(path.join(node.fullPath, child));
|
|
192
332
|
}
|
|
193
333
|
node.stub = false;
|
|
194
334
|
}
|
|
195
335
|
#stubify(filePath, parent) {
|
|
196
|
-
const canonicalPath =
|
|
197
|
-
if (!parent && canonicalPath !==
|
|
198
|
-
throw new Error(
|
|
336
|
+
const canonicalPath = path.resolve(filePath);
|
|
337
|
+
if (!parent && canonicalPath !== path.parse(canonicalPath).root) {
|
|
338
|
+
throw new Error(
|
|
339
|
+
`parent can only be null if path is root. Instead got: ${canonicalPath}`
|
|
340
|
+
);
|
|
199
341
|
}
|
|
200
342
|
const stat = this.fs.lstatSync(canonicalPath);
|
|
201
343
|
let node;
|
|
@@ -225,15 +367,19 @@ var CachingHost = class {
|
|
|
225
367
|
needsFlush: false
|
|
226
368
|
};
|
|
227
369
|
} else {
|
|
228
|
-
throw new Error(
|
|
370
|
+
throw new Error(
|
|
371
|
+
`what is not a file nor symlink nor directory? nothing we care about: ${canonicalPath}`
|
|
372
|
+
);
|
|
229
373
|
}
|
|
230
374
|
if (!parent && node.type === "dir") {
|
|
231
375
|
this.#trees.set(canonicalPath, node);
|
|
232
376
|
return node;
|
|
233
377
|
} else if (parent) {
|
|
234
|
-
parent.dir.set(
|
|
378
|
+
parent.dir.set(path.basename(canonicalPath), node);
|
|
235
379
|
} else {
|
|
236
|
-
throw new Error(
|
|
380
|
+
throw new Error(
|
|
381
|
+
`root can only be a dir, got ${JSON.stringify(node)} for path: ${canonicalPath}`
|
|
382
|
+
);
|
|
237
383
|
}
|
|
238
384
|
return node;
|
|
239
385
|
}
|
|
@@ -242,13 +388,13 @@ var CachingHost = class {
|
|
|
242
388
|
* You should check the `fullPath` of the result.
|
|
243
389
|
*/
|
|
244
390
|
#getNearestAncestorNode(filePath) {
|
|
245
|
-
const canonicalPath =
|
|
246
|
-
const { root } =
|
|
391
|
+
const canonicalPath = path.resolve(filePath);
|
|
392
|
+
const { root } = path.parse(canonicalPath);
|
|
247
393
|
const parts = [];
|
|
248
394
|
let maybePath = canonicalPath;
|
|
249
395
|
while (maybePath !== root) {
|
|
250
|
-
parts.unshift(
|
|
251
|
-
maybePath =
|
|
396
|
+
parts.unshift(path.basename(maybePath));
|
|
397
|
+
maybePath = path.dirname(maybePath);
|
|
252
398
|
}
|
|
253
399
|
let curPath = root;
|
|
254
400
|
let curNode = this.#trees.get(root) ?? this.#stubify(curPath, void 0);
|
|
@@ -257,7 +403,9 @@ var CachingHost = class {
|
|
|
257
403
|
assertNoTombstone(curNode);
|
|
258
404
|
assertNotType(curNode, "file");
|
|
259
405
|
if (curNode.type === "symlink") {
|
|
260
|
-
const linkedNode = this.#getNodeResolvingSymlinks(
|
|
406
|
+
const linkedNode = this.#getNodeResolvingSymlinks(
|
|
407
|
+
path.resolve(path.dirname(curPath), curNode.symlink)
|
|
408
|
+
);
|
|
261
409
|
assertExists(linkedNode);
|
|
262
410
|
assertNoTombstone(linkedNode);
|
|
263
411
|
assertType(linkedNode, "dir");
|
|
@@ -265,16 +413,18 @@ var CachingHost = class {
|
|
|
265
413
|
}
|
|
266
414
|
assertType(curNode, "dir");
|
|
267
415
|
assertNoTombstone(curNode);
|
|
268
|
-
curNode = curNode.dir.get(part) ?? this.#stubify(
|
|
269
|
-
curPath =
|
|
416
|
+
curNode = curNode.dir.get(part) ?? this.#stubify(path.join(curNode.fullPath, part), curNode);
|
|
417
|
+
curPath = path.join(curPath, part);
|
|
270
418
|
}
|
|
271
419
|
} catch (e) {
|
|
272
420
|
}
|
|
273
421
|
return { pathWithSymlinks: curPath, node: curNode };
|
|
274
422
|
}
|
|
275
423
|
#getNode(filePath) {
|
|
276
|
-
const canonicalPath =
|
|
277
|
-
const { pathWithSymlinks, node } = this.#getNearestAncestorNode(
|
|
424
|
+
const canonicalPath = path.resolve(filePath);
|
|
425
|
+
const { pathWithSymlinks, node } = this.#getNearestAncestorNode(
|
|
426
|
+
canonicalPath
|
|
427
|
+
);
|
|
278
428
|
if (pathWithSymlinks === canonicalPath) {
|
|
279
429
|
return node;
|
|
280
430
|
}
|
|
@@ -287,16 +437,18 @@ var CachingHost = class {
|
|
|
287
437
|
return this.#getNodeResolvingSymlinks(node.symlink, follows--);
|
|
288
438
|
}
|
|
289
439
|
mkdir(filePath, opts = { recursive: false }) {
|
|
290
|
-
const canonicalPath =
|
|
291
|
-
const { node, pathWithSymlinks } = this.#getNearestAncestorNode(
|
|
440
|
+
const canonicalPath = path.resolve(filePath);
|
|
441
|
+
const { node, pathWithSymlinks } = this.#getNearestAncestorNode(
|
|
442
|
+
canonicalPath
|
|
443
|
+
);
|
|
292
444
|
if (filePath === pathWithSymlinks) {
|
|
293
445
|
assertType(node, "dir");
|
|
294
446
|
assertHasParent(node);
|
|
295
447
|
if (!node.tombstone) return;
|
|
296
|
-
} else if (
|
|
448
|
+
} else if (path.dirname(filePath) === pathWithSymlinks) {
|
|
297
449
|
assertType(node, "dir");
|
|
298
450
|
assertNoTombstone(node);
|
|
299
|
-
node.dir.set(
|
|
451
|
+
node.dir.set(path.basename(filePath), {
|
|
300
452
|
type: "dir",
|
|
301
453
|
fullPath: filePath,
|
|
302
454
|
parent: node,
|
|
@@ -305,15 +457,17 @@ var CachingHost = class {
|
|
|
305
457
|
});
|
|
306
458
|
return;
|
|
307
459
|
}
|
|
308
|
-
if (!opts.recursive &&
|
|
460
|
+
if (!opts.recursive && path.dirname(canonicalPath) !== pathWithSymlinks) {
|
|
309
461
|
throw new Error("no such file or directory");
|
|
310
462
|
}
|
|
311
463
|
const rootPath = pathWithSymlinks;
|
|
312
464
|
let maybePath = canonicalPath;
|
|
313
465
|
const toMake = [];
|
|
314
466
|
while (maybePath !== rootPath) {
|
|
315
|
-
toMake.unshift(
|
|
316
|
-
|
|
467
|
+
toMake.unshift(
|
|
468
|
+
path.resolve(node.fullPath, path.relative(rootPath, maybePath))
|
|
469
|
+
);
|
|
470
|
+
maybePath = path.dirname(maybePath);
|
|
317
471
|
}
|
|
318
472
|
for (const dirToMake of toMake) {
|
|
319
473
|
this.mkdir(dirToMake);
|
|
@@ -366,7 +520,7 @@ var CachingHost = class {
|
|
|
366
520
|
}
|
|
367
521
|
writeFile(filePath, body, opts) {
|
|
368
522
|
const fileContentsAsBuffer = typeof body === "string" ? Buffer.from(body, opts == null ? void 0 : opts.encoding) : Buffer.from(body);
|
|
369
|
-
const canonicalPath =
|
|
523
|
+
const canonicalPath = path.resolve(filePath);
|
|
370
524
|
const existingNode = this.#getNodeResolvingSymlinks(canonicalPath);
|
|
371
525
|
if (existingNode) {
|
|
372
526
|
if (existingNode.type === "dir") {
|
|
@@ -379,11 +533,13 @@ var CachingHost = class {
|
|
|
379
533
|
});
|
|
380
534
|
return;
|
|
381
535
|
}
|
|
382
|
-
const maybeDirNode = this.#getNodeResolvingSymlinks(
|
|
536
|
+
const maybeDirNode = this.#getNodeResolvingSymlinks(
|
|
537
|
+
path.dirname(canonicalPath)
|
|
538
|
+
);
|
|
383
539
|
assertExists(maybeDirNode);
|
|
384
540
|
assertType(maybeDirNode, "dir");
|
|
385
541
|
assertNoTombstone(maybeDirNode);
|
|
386
|
-
maybeDirNode.dir.set(
|
|
542
|
+
maybeDirNode.dir.set(path.basename(canonicalPath), {
|
|
387
543
|
type: "file",
|
|
388
544
|
fullPath: canonicalPath,
|
|
389
545
|
parent: maybeDirNode,
|
|
@@ -392,7 +548,7 @@ var CachingHost = class {
|
|
|
392
548
|
});
|
|
393
549
|
}
|
|
394
550
|
deleteFile(filePath) {
|
|
395
|
-
const canonicalPath =
|
|
551
|
+
const canonicalPath = path.resolve(filePath);
|
|
396
552
|
const node = this.#getNode(canonicalPath);
|
|
397
553
|
if (!node || node.type === "file" && node.tombstone === true) return;
|
|
398
554
|
assertNotType(node, "dir");
|
|
@@ -427,265 +583,165 @@ var CachingHost = class {
|
|
|
427
583
|
async #flushSymlinkNode(node) {
|
|
428
584
|
if (!node.needsFlush) return;
|
|
429
585
|
try {
|
|
430
|
-
const linkValue = await this.fs.promises.readlink(node.fullPath);
|
|
431
|
-
if (linkValue === node.symlink) {
|
|
432
|
-
return;
|
|
433
|
-
}
|
|
434
|
-
} catch (e) {
|
|
435
|
-
}
|
|
436
|
-
return this.fs.promises.symlink(node.symlink, node.fullPath);
|
|
437
|
-
}
|
|
438
|
-
async #flushDirNode(node) {
|
|
439
|
-
if (!node.tombstone && node.needsFlush) {
|
|
440
|
-
try {
|
|
441
|
-
await this.fs.promises.access(node.fullPath);
|
|
442
|
-
} catch (e) {
|
|
443
|
-
await this.fs.promises.mkdir(node.fullPath);
|
|
444
|
-
}
|
|
445
|
-
}
|
|
446
|
-
const promises2 = [];
|
|
447
|
-
for (const child of node.dir.values()) {
|
|
448
|
-
if (node.tombstone && !child.tombstone) {
|
|
449
|
-
throw new Error("Unexpected failure during sanity check. A non-deleted child is on a deleted dir");
|
|
450
|
-
}
|
|
451
|
-
if (child.type === "dir") {
|
|
452
|
-
promises2.push(this.#flushDirNode(child));
|
|
453
|
-
} else if (child.type === "file") {
|
|
454
|
-
promises2.push(this.#flushFileNode(child));
|
|
455
|
-
} else if (child.type === "symlink") {
|
|
456
|
-
promises2.push(this.#flushSymlinkNode(child));
|
|
457
|
-
} else {
|
|
458
|
-
throw new Error("should never happen");
|
|
459
|
-
}
|
|
460
|
-
}
|
|
461
|
-
await Promise.all(promises2);
|
|
462
|
-
if (node.tombstone) {
|
|
463
|
-
return this.fs.promises.rmdir(node.fullPath);
|
|
464
|
-
}
|
|
465
|
-
return;
|
|
466
|
-
}
|
|
467
|
-
flush() {
|
|
468
|
-
const promises2 = [];
|
|
469
|
-
for (const rootNode of this.#trees.values()) {
|
|
470
|
-
promises2.push(this.#flushDirNode(rootNode));
|
|
471
|
-
}
|
|
472
|
-
return Promise.all(promises2);
|
|
473
|
-
}
|
|
474
|
-
};
|
|
475
|
-
|
|
476
|
-
// src/matchesAnyGlob.ts
|
|
477
|
-
import micromatch from "micromatch";
|
|
478
|
-
|
|
479
|
-
// src/nanosecondsToSanity.ts
|
|
480
|
-
function nanosecondsToSanity(n, precision = 9) {
|
|
481
|
-
return n / BigInt(1e9) + "." + ("" + n % BigInt(1e9)).padStart(9, "0").substring(0, precision) + "s";
|
|
482
|
-
}
|
|
483
|
-
|
|
484
|
-
// src/Table.ts
|
|
485
|
-
var Table = class {
|
|
486
|
-
#rows = [];
|
|
487
|
-
#config;
|
|
488
|
-
#columnWidths = [];
|
|
489
|
-
#footer = [];
|
|
490
|
-
#footerRowConfig;
|
|
491
|
-
#totalWidth = 0;
|
|
492
|
-
constructor(config) {
|
|
493
|
-
this.#config = {
|
|
494
|
-
padding: 2,
|
|
495
|
-
...config
|
|
496
|
-
};
|
|
497
|
-
this.#columnWidths.fill(0, 0, config.columns.length);
|
|
498
|
-
if (config.showFooter) {
|
|
499
|
-
this.#footerRowConfig = [];
|
|
500
|
-
for (const columnConfig of config.columns) {
|
|
501
|
-
if (columnConfig.footer === void 0) {
|
|
502
|
-
throw new Error("Must specify footer fields when showFooter is true");
|
|
503
|
-
} else if (typeof columnConfig.footer === "string") {
|
|
504
|
-
this.#footerRowConfig.push({
|
|
505
|
-
type: "string",
|
|
506
|
-
alignment: "left",
|
|
507
|
-
aggregate: "static",
|
|
508
|
-
value: columnConfig.footer
|
|
509
|
-
});
|
|
510
|
-
} else if ("value" in columnConfig.footer) {
|
|
511
|
-
this.#footerRowConfig.push({
|
|
512
|
-
type: "string",
|
|
513
|
-
alignment: "left",
|
|
514
|
-
...columnConfig.footer
|
|
515
|
-
});
|
|
516
|
-
} else if ("aggregate" in columnConfig.footer) {
|
|
517
|
-
if (columnConfig.type !== "bigint") throw new Error("expecting bigint for aggregate");
|
|
518
|
-
this.#footerRowConfig.push({
|
|
519
|
-
type: columnConfig.type,
|
|
520
|
-
renderAs: columnConfig.renderAs,
|
|
521
|
-
precision: columnConfig.precision,
|
|
522
|
-
alignment: "right",
|
|
523
|
-
...columnConfig.footer
|
|
524
|
-
});
|
|
525
|
-
}
|
|
526
|
-
}
|
|
527
|
-
}
|
|
528
|
-
}
|
|
529
|
-
addRow(...data) {
|
|
530
|
-
this.#rows.push(data);
|
|
531
|
-
}
|
|
532
|
-
#sumColumn(c) {
|
|
533
|
-
let total = BigInt(0);
|
|
534
|
-
for (const row of this.#rows) {
|
|
535
|
-
total += row[c];
|
|
536
|
-
}
|
|
537
|
-
return total;
|
|
538
|
-
}
|
|
539
|
-
#updateFooterRow() {
|
|
540
|
-
const footerRowConfig = this.#footerRowConfig;
|
|
541
|
-
if (footerRowConfig) {
|
|
542
|
-
for (let c = 0; c < footerRowConfig.length; c++) {
|
|
543
|
-
const footerColConfig = footerRowConfig[c];
|
|
544
|
-
switch (footerColConfig.aggregate) {
|
|
545
|
-
case "sum":
|
|
546
|
-
this.#footer[c] = this.#sumColumn(c);
|
|
547
|
-
break;
|
|
548
|
-
case "average":
|
|
549
|
-
this.#footer[c] = this.#sumColumn(c) / BigInt(this.#rows.length);
|
|
550
|
-
break;
|
|
551
|
-
case "static":
|
|
552
|
-
this.#footer[c] = footerColConfig.value;
|
|
553
|
-
break;
|
|
554
|
-
}
|
|
555
|
-
}
|
|
556
|
-
}
|
|
557
|
-
}
|
|
558
|
-
#calculateColumnWidths() {
|
|
559
|
-
var _a;
|
|
560
|
-
this.#columnWidths.fill(0, 0, this.#config.columns.length);
|
|
561
|
-
for (let c = 0; c < this.#config.columns.length; c++) {
|
|
562
|
-
const colConfig = this.#config.columns[c];
|
|
563
|
-
this.#columnWidths[c] = Math.max(
|
|
564
|
-
(this.#config.columns[c].header ?? "").length,
|
|
565
|
-
...this.#rows.map((a) => this.#getCellValueAsString(a[c], colConfig).length),
|
|
566
|
-
this.#footer && this.#footerRowConfig ? this.#getCellValueAsString(((_a = this.#footer) == null ? void 0 : _a[c]) ?? "", this.#footerRowConfig[c]).length : 0
|
|
567
|
-
);
|
|
568
|
-
}
|
|
569
|
-
this.#totalWidth = 0;
|
|
570
|
-
for (const colWidth of this.#columnWidths) {
|
|
571
|
-
this.#totalWidth += colWidth;
|
|
572
|
-
}
|
|
573
|
-
this.#totalWidth += (this.#columnWidths.length - 1) * this.#config.padding;
|
|
574
|
-
}
|
|
575
|
-
#printSeparator(fillString) {
|
|
576
|
-
const paddingString = "".padStart(this.#config.padding, " ");
|
|
577
|
-
let hr2 = "";
|
|
578
|
-
for (let c = 0; c < this.#columnWidths.length; c++) {
|
|
579
|
-
hr2 += "".padStart(this.#columnWidths[c], fillString) + paddingString;
|
|
580
|
-
}
|
|
581
|
-
hr2 = hr2.trimRight();
|
|
582
|
-
console.log(hr2);
|
|
583
|
-
}
|
|
584
|
-
#printHeaderRow() {
|
|
585
|
-
if (this.#config.showHeader) {
|
|
586
|
-
const colConfigs = this.#config.columns;
|
|
587
|
-
const paddingString = "".padStart(this.#config.padding, " ");
|
|
588
|
-
let hr = "";
|
|
589
|
-
for (let c = 0; c < colConfigs.length; c++) {
|
|
590
|
-
const heading = colConfigs[c].header ?? "";
|
|
591
|
-
hr += heading.padEnd(this.#columnWidths[c], " ") + paddingString;
|
|
592
|
-
}
|
|
593
|
-
hr = hr.trimRight();
|
|
594
|
-
console.log(hr);
|
|
595
|
-
this.#printSeparator("-");
|
|
596
|
-
}
|
|
597
|
-
}
|
|
598
|
-
#printFooterRow() {
|
|
599
|
-
const footerRow = this.#footer;
|
|
600
|
-
if (footerRow) {
|
|
601
|
-
this.#printSeparator("=");
|
|
602
|
-
const paddingString = "".padStart(this.#config.padding, " ");
|
|
603
|
-
let hr = "";
|
|
604
|
-
for (let c = 0; c < footerRow.length; c++) {
|
|
605
|
-
hr += this.#getCellValueAligned(footerRow[c], this.#footerRowConfig[c], c) + paddingString;
|
|
606
|
-
}
|
|
607
|
-
hr = hr.trimRight();
|
|
608
|
-
console.log(hr);
|
|
609
|
-
}
|
|
610
|
-
}
|
|
611
|
-
print() {
|
|
612
|
-
if (this.#config.sortColumn !== void 0) {
|
|
613
|
-
}
|
|
614
|
-
this.#updateFooterRow();
|
|
615
|
-
this.#calculateColumnWidths();
|
|
616
|
-
console.log();
|
|
617
|
-
console.log(`${this.#config.title}`);
|
|
618
|
-
console.log("".padStart(this.#totalWidth, "="));
|
|
619
|
-
const paddingString = "".padStart(this.#config.padding, " ");
|
|
620
|
-
if (this.#config.showHeader) {
|
|
621
|
-
this.#printHeaderRow();
|
|
622
|
-
}
|
|
623
|
-
for (let r = 0; r < this.#rows.length; r++) {
|
|
624
|
-
let rowText = "";
|
|
625
|
-
for (let c = 0; c < this.#config.columns.length; c++) {
|
|
626
|
-
rowText += this.getEntryAsStringAligned(c, r) + paddingString;
|
|
586
|
+
const linkValue = await this.fs.promises.readlink(node.fullPath);
|
|
587
|
+
if (linkValue === node.symlink) {
|
|
588
|
+
return;
|
|
627
589
|
}
|
|
628
|
-
|
|
629
|
-
console.log(rowText);
|
|
590
|
+
} catch (e) {
|
|
630
591
|
}
|
|
631
|
-
|
|
632
|
-
console.log();
|
|
592
|
+
return this.fs.promises.symlink(node.symlink, node.fullPath);
|
|
633
593
|
}
|
|
634
|
-
#
|
|
635
|
-
if (
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
594
|
+
async #flushDirNode(node) {
|
|
595
|
+
if (!node.tombstone && node.needsFlush) {
|
|
596
|
+
try {
|
|
597
|
+
await this.fs.promises.access(node.fullPath);
|
|
598
|
+
} catch (e) {
|
|
599
|
+
await this.fs.promises.mkdir(node.fullPath);
|
|
600
|
+
}
|
|
639
601
|
}
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
602
|
+
const promises2 = [];
|
|
603
|
+
for (const child of node.dir.values()) {
|
|
604
|
+
if (node.tombstone && !child.tombstone) {
|
|
605
|
+
throw new Error(
|
|
606
|
+
"Unexpected failure during sanity check. A non-deleted child is on a deleted dir"
|
|
607
|
+
);
|
|
608
|
+
}
|
|
609
|
+
if (child.type === "dir") {
|
|
610
|
+
promises2.push(this.#flushDirNode(child));
|
|
611
|
+
} else if (child.type === "file") {
|
|
612
|
+
promises2.push(this.#flushFileNode(child));
|
|
613
|
+
} else if (child.type === "symlink") {
|
|
614
|
+
promises2.push(this.#flushSymlinkNode(child));
|
|
615
|
+
} else {
|
|
616
|
+
throw new Error("should never happen");
|
|
617
|
+
}
|
|
647
618
|
}
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
return result.padStart(this.#columnWidths[column]);
|
|
619
|
+
await Promise.all(promises2);
|
|
620
|
+
if (node.tombstone) {
|
|
621
|
+
return this.fs.promises.rmdir(node.fullPath);
|
|
652
622
|
}
|
|
623
|
+
return;
|
|
653
624
|
}
|
|
654
|
-
|
|
655
|
-
const
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
} else {
|
|
659
|
-
return "" + this.#rows[rowNum][colNum];
|
|
625
|
+
flush() {
|
|
626
|
+
const promises2 = [];
|
|
627
|
+
for (const rootNode of this.#trees.values()) {
|
|
628
|
+
promises2.push(this.#flushDirNode(rootNode));
|
|
660
629
|
}
|
|
630
|
+
return Promise.all(promises2);
|
|
661
631
|
}
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
632
|
+
};
|
|
633
|
+
|
|
634
|
+
// src/findWorkspaceDir.ts
|
|
635
|
+
import { findUp } from "find-up";
|
|
636
|
+
import * as fs from "fs";
|
|
637
|
+
import * as path2 from "path";
|
|
638
|
+
async function findPnpmWorkspaceDir(cwd) {
|
|
639
|
+
const workspaceManifestLocation = await findUp("pnpm-workspace.yaml", {
|
|
640
|
+
cwd: await fs.promises.realpath(cwd)
|
|
641
|
+
});
|
|
642
|
+
return workspaceManifestLocation && path2.dirname(workspaceManifestLocation);
|
|
643
|
+
}
|
|
644
|
+
async function findWorkspaceDir(host, dir) {
|
|
645
|
+
const maybePnpmWorkspaceDir = await findPnpmWorkspaceDir(dir);
|
|
646
|
+
if (maybePnpmWorkspaceDir != null) {
|
|
647
|
+
return maybePnpmWorkspaceDir;
|
|
648
|
+
}
|
|
649
|
+
const packagePath = path2.join(dir, "package.json");
|
|
650
|
+
if (host.exists(packagePath)) {
|
|
651
|
+
const packageJson = host.readJson(packagePath);
|
|
652
|
+
if (packageJson.workspaces !== void 0) {
|
|
653
|
+
return dir;
|
|
669
654
|
}
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
655
|
+
}
|
|
656
|
+
const nextDir = path2.normalize(path2.join(dir, ".."));
|
|
657
|
+
if (nextDir === dir) {
|
|
658
|
+
return void 0;
|
|
659
|
+
}
|
|
660
|
+
return findWorkspaceDir(host, nextDir);
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
// src/getPackageNameToDir.ts
|
|
664
|
+
import { join as pathJoin } from "path";
|
|
665
|
+
|
|
666
|
+
// src/getWorkspacePackageDirs.ts
|
|
667
|
+
import { findPackages } from "find-packages";
|
|
668
|
+
import { existsSync } from "fs";
|
|
669
|
+
import * as glob from "glob";
|
|
670
|
+
import * as fs2 from "node:fs";
|
|
671
|
+
import * as path3 from "node:path";
|
|
672
|
+
import readYamlFile from "read-yaml-file";
|
|
673
|
+
async function findPNPMWorkspacePackages(workspaceRoot) {
|
|
674
|
+
workspaceRoot = fs2.realpathSync(workspaceRoot);
|
|
675
|
+
const workspaceManifest = await readYamlFile.default(
|
|
676
|
+
path3.join(workspaceRoot, "pnpm-workspace.yaml")
|
|
677
|
+
);
|
|
678
|
+
return findPackages(workspaceRoot, {
|
|
679
|
+
ignore: ["**/node_modules/**", "**/bower_components/**"],
|
|
680
|
+
includeRoot: true,
|
|
681
|
+
patterns: workspaceManifest.packages
|
|
682
|
+
});
|
|
683
|
+
}
|
|
684
|
+
async function getWorkspacePackageDirs(host, workspaceDir, resolvePaths = false) {
|
|
685
|
+
const packageJson = host.readJson(
|
|
686
|
+
path3.join(workspaceDir, "package.json")
|
|
687
|
+
);
|
|
688
|
+
const isPnpmWorkspace = host.exists(
|
|
689
|
+
path3.join(workspaceDir, "pnpm-workspace.yaml")
|
|
690
|
+
);
|
|
691
|
+
if (isPnpmWorkspace) {
|
|
692
|
+
const workspacePackages = await findPNPMWorkspacePackages(workspaceDir);
|
|
693
|
+
if (workspacePackages.length === 0) {
|
|
694
|
+
throw new Error("Invalid workspaceDir: " + workspaceDir);
|
|
674
695
|
}
|
|
696
|
+
return workspacePackages.map((project) => project.dir).filter((d) => d !== workspaceDir);
|
|
675
697
|
}
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
this.#footer && this.#footerRowConfig ? this.#getCellValueAsString(this.#footer[colNum], this.#footerRowConfig[colNum]).length : 0
|
|
698
|
+
if (!packageJson.workspaces) {
|
|
699
|
+
throw new Error(
|
|
700
|
+
"Unsupported! Monorepo is not backed by either pnpm nor yarn workspaces."
|
|
680
701
|
);
|
|
681
|
-
|
|
682
|
-
|
|
702
|
+
}
|
|
703
|
+
const ret = [];
|
|
704
|
+
const packageGlobs = Array.isArray(packageJson.workspaces) ? packageJson.workspaces : packageJson.workspaces.packages || [];
|
|
705
|
+
for (const pattern of packageGlobs) {
|
|
706
|
+
for (const packagePath of glob.sync(pattern, { cwd: workspaceDir })) {
|
|
707
|
+
const packageJsonPath = path3.join(
|
|
708
|
+
workspaceDir,
|
|
709
|
+
packagePath,
|
|
710
|
+
"package.json"
|
|
711
|
+
);
|
|
712
|
+
if (existsSync(packageJsonPath)) {
|
|
713
|
+
if (resolvePaths === true) {
|
|
714
|
+
ret.push(path3.resolve(path3.join(workspaceDir, packagePath)));
|
|
715
|
+
} else {
|
|
716
|
+
ret.push(packagePath);
|
|
717
|
+
}
|
|
718
|
+
}
|
|
683
719
|
}
|
|
684
|
-
return maxWidth;
|
|
685
720
|
}
|
|
686
|
-
|
|
721
|
+
return ret;
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
// src/getPackageNameToDir.ts
|
|
725
|
+
async function getPackageNameToDir(host, workspaceDir, resolvePaths = false) {
|
|
726
|
+
const ret = /* @__PURE__ */ new Map();
|
|
727
|
+
const workspacePackages = await getWorkspacePackageDirs(
|
|
728
|
+
host,
|
|
729
|
+
workspaceDir,
|
|
730
|
+
resolvePaths
|
|
731
|
+
);
|
|
732
|
+
for (const packageDir of workspacePackages) {
|
|
733
|
+
const packagePath = pathJoin(packageDir, "package.json");
|
|
734
|
+
const { name } = host.readJson(packagePath);
|
|
735
|
+
if (name === void 0) {
|
|
736
|
+
throw new Error(`Package needs a name: ${packagePath}`);
|
|
737
|
+
}
|
|
738
|
+
ret.set(name, packageDir);
|
|
739
|
+
}
|
|
740
|
+
return ret;
|
|
741
|
+
}
|
|
687
742
|
|
|
688
743
|
// src/matchesAnyGlob.ts
|
|
744
|
+
import micromatch from "micromatch";
|
|
689
745
|
var cache = /* @__PURE__ */ new Map();
|
|
690
746
|
var singleMatcherCache = /* @__PURE__ */ new Map();
|
|
691
747
|
var compiledGlobCache = /* @__PURE__ */ new Map();
|
|
@@ -755,63 +811,53 @@ matchesAnyGlob.printStats = () => {
|
|
|
755
811
|
table.print();
|
|
756
812
|
};
|
|
757
813
|
|
|
758
|
-
// src/
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
814
|
+
// src/mutateJson.ts
|
|
815
|
+
function mutateJson(path4, host, mutator) {
|
|
816
|
+
let file = host.readJson(path4);
|
|
817
|
+
file = mutator(file);
|
|
818
|
+
host.writeJson(path4, file);
|
|
819
|
+
}
|
|
820
|
+
|
|
821
|
+
// src/SimpleHost.ts
|
|
822
|
+
import * as realFs2 from "fs";
|
|
823
|
+
var SimpleHost = class {
|
|
824
|
+
constructor(fs3 = realFs2) {
|
|
825
|
+
this.fs = fs3;
|
|
762
826
|
}
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
827
|
+
mkdir(directoryPath, opts) {
|
|
828
|
+
this.fs.mkdirSync(directoryPath, { recursive: (opts == null ? void 0 : opts.recursive) ?? false });
|
|
829
|
+
}
|
|
830
|
+
rmdir(directoryPath) {
|
|
831
|
+
this.fs.rmdirSync(directoryPath);
|
|
832
|
+
}
|
|
833
|
+
exists(path4) {
|
|
834
|
+
return this.fs.existsSync(path4);
|
|
835
|
+
}
|
|
836
|
+
writeFile(path4, body, opts) {
|
|
837
|
+
if (opts) {
|
|
838
|
+
this.fs.writeFileSync(path4, body, { encoding: opts.encoding });
|
|
774
839
|
} else {
|
|
775
|
-
|
|
776
|
-
data.count++;
|
|
840
|
+
this.fs.writeFileSync(path4, body);
|
|
777
841
|
}
|
|
778
|
-
this.#last = data;
|
|
779
842
|
}
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
this.#last.total += time;
|
|
784
|
-
this.#last = void 0;
|
|
843
|
+
readFile(path4, opts) {
|
|
844
|
+
if (opts == null ? void 0 : opts.asJson) {
|
|
845
|
+
return JSON.parse(this.fs.readFileSync(path4, "utf-8"));
|
|
785
846
|
}
|
|
847
|
+
return this.fs.readFileSync(path4, opts == null ? void 0 : opts.encoding);
|
|
786
848
|
}
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
},
|
|
800
|
-
{ header: "Task", type: "string", alignment: "left", footer: "TOTAL" },
|
|
801
|
-
{ header: "Count", type: "bigint", footer: { aggregate: "sum" } },
|
|
802
|
-
{ header: "Avg", type: "bigint", footer: { aggregate: "average" } }
|
|
803
|
-
]
|
|
804
|
-
});
|
|
805
|
-
for (const [name, value] of this.#data) {
|
|
806
|
-
table.addRow(
|
|
807
|
-
value.total,
|
|
808
|
-
name,
|
|
809
|
-
BigInt(value.count),
|
|
810
|
-
// fixme this can be a number later
|
|
811
|
-
value.total / BigInt(value.count)
|
|
812
|
-
);
|
|
813
|
-
}
|
|
814
|
-
table.print();
|
|
849
|
+
deleteFile(path4) {
|
|
850
|
+
this.fs.unlinkSync(path4);
|
|
851
|
+
}
|
|
852
|
+
readJson(filename) {
|
|
853
|
+
const contents = this.fs.readFileSync(filename, "utf-8");
|
|
854
|
+
return JSON.parse(contents);
|
|
855
|
+
}
|
|
856
|
+
writeJson(path4, o) {
|
|
857
|
+
return this.fs.writeFileSync(path4, JSON.stringify(o, void 0, 2) + "\n");
|
|
858
|
+
}
|
|
859
|
+
flush() {
|
|
860
|
+
return Promise.resolve();
|
|
815
861
|
}
|
|
816
862
|
};
|
|
817
863
|
|
|
@@ -871,13 +917,13 @@ export {
|
|
|
871
917
|
nanosecondsToSanity
|
|
872
918
|
};
|
|
873
919
|
/*!
|
|
874
|
-
* Copyright
|
|
920
|
+
* Copyright 2022 Palantir Technologies, Inc.
|
|
875
921
|
*
|
|
876
922
|
* Licensed under the MIT license. See LICENSE file in the project root for details.
|
|
877
923
|
*
|
|
878
924
|
*/
|
|
879
925
|
/*!
|
|
880
|
-
* Copyright
|
|
926
|
+
* Copyright 2019 Palantir Technologies, Inc.
|
|
881
927
|
*
|
|
882
928
|
* Licensed under the MIT license. See LICENSE file in the project root for details.
|
|
883
929
|
*
|