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