@monorepolint/utils 0.6.0-alpha.2 → 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.
Files changed (56) hide show
  1. package/.turbo/turbo-clean.log +1 -1
  2. package/.turbo/turbo-compile-typescript.log +1 -1
  3. package/.turbo/turbo-lint.log +7 -7
  4. package/.turbo/turbo-test.log +14 -10
  5. package/.turbo/turbo-transpile-typescript.log +3 -3
  6. package/CHANGELOG.md +2 -0
  7. package/build/js/index.js +493 -443
  8. package/build/js/index.js.map +1 -1
  9. package/build/tsconfig.tsbuildinfo +1 -1
  10. package/build/types/CachingHost.d.ts.map +1 -1
  11. package/build/types/Host.d.ts.map +1 -1
  12. package/build/types/PackageJson.d.ts.map +1 -1
  13. package/build/types/SimpleHost.d.ts.map +1 -1
  14. package/build/types/Table.d.ts.map +1 -1
  15. package/build/types/findWorkspaceDir.d.ts.map +1 -1
  16. package/build/types/getPackageNameToDir.d.ts.map +1 -1
  17. package/build/types/getWorkspacePackageDirs.d.ts.map +1 -1
  18. package/build/types/index.d.ts +7 -7
  19. package/build/types/index.d.ts.map +1 -1
  20. package/build/types/matchesAnyGlob.d.ts.map +1 -1
  21. package/build/types/mutateJson.d.ts.map +1 -1
  22. package/build/types/nanosecondsToSanity.d.ts.map +1 -1
  23. package/coverage/AggregateTiming.ts.html +2 -2
  24. package/coverage/CachingHost.ts.html +258 -42
  25. package/coverage/Host.ts.html +15 -3
  26. package/coverage/PackageJson.ts.html +4 -4
  27. package/coverage/SimpleHost.ts.html +40 -7
  28. package/coverage/Table.ts.html +148 -31
  29. package/coverage/Timing.ts.html +1 -1
  30. package/coverage/clover.xml +533 -389
  31. package/coverage/coverage-final.json +13 -13
  32. package/coverage/findWorkspaceDir.ts.html +4 -4
  33. package/coverage/getPackageNameToDir.ts.html +18 -6
  34. package/coverage/getWorkspacePackageDirs.ts.html +174 -138
  35. package/coverage/index.html +40 -40
  36. package/coverage/index.ts.html +30 -30
  37. package/coverage/matchesAnyGlob.ts.html +37 -10
  38. package/coverage/mutateJson.ts.html +17 -5
  39. package/coverage/nanosecondsToSanity.ts.html +11 -5
  40. package/package.json +1 -2
  41. package/src/AggregateTiming.ts +1 -1
  42. package/src/CachingHost.ts +106 -34
  43. package/src/Host.ts +5 -1
  44. package/src/PackageJson.ts +3 -3
  45. package/src/SimpleHost.ts +14 -3
  46. package/src/Table.ts +62 -23
  47. package/src/__tests__/CachingHost.spec.ts +203 -166
  48. package/src/findWorkspaceDir.ts +3 -3
  49. package/src/getPackageNameToDir.ts +6 -2
  50. package/src/getWorkspacePackageDirs.ts +22 -10
  51. package/src/index.ts +7 -7
  52. package/src/matchesAnyGlob.ts +12 -3
  53. package/src/mutateJson.ts +5 -1
  54. package/src/nanosecondsToSanity.ts +3 -1
  55. package/vitest.config.mjs +10 -7
  56. package/vitest.config.mjs.timestamp-1736878329730-aa478e2241542.mjs +2 -2
package/build/js/index.js CHANGED
@@ -1,149 +1,291 @@
1
- // src/getWorkspacePackageDirs.ts
2
- import { existsSync } from "fs";
3
- import * as glob from "glob";
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
- async function getWorkspacePackageDirs(host, workspaceDir, resolvePaths = false) {
20
- const packageJson = host.readJson(path.join(workspaceDir, "package.json"));
21
- const isPnpmWorkspace = host.exists(path.join(workspaceDir, "pnpm-workspace.yaml"));
22
- if (isPnpmWorkspace) {
23
- const workspacePackages = await findPNPMWorkspacePackages(workspaceDir);
24
- if (workspacePackages.length === 0) {
25
- throw new Error("Invalid workspaceDir: " + workspaceDir);
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
- if (!packageJson.workspaces) {
30
- throw new Error("Unsupported! Monorepo is not backed by either pnpm nor yarn workspaces.");
53
+ addRow(...data) {
54
+ this.#rows.push(data);
31
55
  }
32
- const ret = [];
33
- const packageGlobs = Array.isArray(packageJson.workspaces) ? packageJson.workspaces : packageJson.workspaces.packages || [];
34
- for (const pattern of packageGlobs) {
35
- for (const packagePath of glob.sync(pattern, { cwd: workspaceDir })) {
36
- const packageJsonPath = path.join(workspaceDir, packagePath, "package.json");
37
- if (existsSync(packageJsonPath)) {
38
- if (resolvePaths === true) {
39
- ret.push(path.resolve(path.join(workspaceDir, packagePath)));
40
- } else {
41
- ret.push(packagePath);
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
- return ret;
47
- }
48
-
49
- // src/mutateJson.ts
50
- function mutateJson(path4, host, mutator) {
51
- let file = host.readJson(path4);
52
- file = mutator(file);
53
- host.writeJson(path4, file);
54
- }
55
-
56
- // src/findWorkspaceDir.ts
57
- import * as path2 from "path";
58
- import * as fs2 from "fs";
59
- import { findUp } from "find-up";
60
- async function findPnpmWorkspaceDir(cwd) {
61
- const workspaceManifestLocation = await findUp("pnpm-workspace.yaml", {
62
- cwd: await fs2.promises.realpath(cwd)
63
- });
64
- return workspaceManifestLocation && path2.dirname(workspaceManifestLocation);
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(
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
- const packagePath = path2.join(dir, "package.json");
72
- if (host.exists(packagePath)) {
73
- const packageJson = host.readJson(packagePath);
74
- if (packageJson.workspaces !== void 0) {
75
- return dir;
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
- const nextDir = path2.normalize(path2.join(dir, ".."));
79
- if (nextDir === dir) {
80
- return void 0;
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
- return findWorkspaceDir(host, nextDir);
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}`);
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
- return ret;
99
- }
100
-
101
- // src/SimpleHost.ts
102
- import * as realFs from "fs";
103
- var SimpleHost = class {
104
- constructor(fs3 = realFs) {
105
- this.fs = fs3;
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
- mkdir(directoryPath, opts) {
108
- this.fs.mkdirSync(directoryPath, { recursive: (opts == null ? void 0 : opts.recursive) ?? false });
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
- rmdir(directoryPath) {
111
- this.fs.rmdirSync(directoryPath);
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
- exists(path4) {
114
- return this.fs.existsSync(path4);
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
- writeFile(path4, body, opts) {
117
- if (opts) {
118
- this.fs.writeFileSync(path4, body, { encoding: opts.encoding });
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.fs.writeFileSync(path4, body);
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]);
209
+ }
210
+ }
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);
221
+ }
222
+ return maxWidth;
223
+ }
224
+ };
225
+
226
+ // src/AggregateTiming.ts
227
+ var AggregateTiming = class {
228
+ constructor(title) {
229
+ this.title = title;
230
+ }
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++;
121
245
  }
246
+ this.#last = data;
122
247
  }
123
- readFile(path4, opts) {
124
- if (opts == null ? void 0 : opts.asJson) {
125
- return JSON.parse(this.fs.readFileSync(path4, "utf-8"));
248
+ stop() {
249
+ const time = process.hrtime.bigint();
250
+ if (this.#last) {
251
+ this.#last.total += time;
252
+ this.#last = void 0;
126
253
  }
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
254
  }
139
- flush() {
140
- return Promise.resolve();
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 realFs2 from "node:fs";
146
- import * as path3 from "node:path";
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,7 +312,7 @@ function assertHasParent(node) {
170
312
  }
171
313
  }
172
314
  var CachingHost = class {
173
- constructor(fs3 = realFs2) {
315
+ constructor(fs3 = realFs) {
174
316
  this.fs = fs3;
175
317
  }
176
318
  // We need many trees because of windows, key is the `root`
@@ -183,19 +325,21 @@ var CachingHost = class {
183
325
  parent: node.parent,
184
326
  dir: node.dir
185
327
  };
186
- node.parent.dir.set(path3.basename(node.fullPath), newNode);
328
+ node.parent.dir.set(path.basename(node.fullPath), newNode);
187
329
  return newNode;
188
330
  }
189
331
  #unstubDirectory(node) {
190
332
  for (const child of this.fs.readdirSync(node.fullPath)) {
191
- this.#getNode(path3.join(node.fullPath, child));
333
+ this.#getNode(path.join(node.fullPath, child));
192
334
  }
193
335
  node.stub = false;
194
336
  }
195
337
  #stubify(filePath, parent) {
196
- const canonicalPath = path3.resolve(filePath);
197
- if (!parent && canonicalPath !== path3.parse(canonicalPath).root) {
198
- throw new Error(`parent can only be null if path is root. Instead got: ${canonicalPath}`);
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
+ );
199
343
  }
200
344
  const stat = this.fs.lstatSync(canonicalPath);
201
345
  let node;
@@ -225,15 +369,19 @@ var CachingHost = class {
225
369
  needsFlush: false
226
370
  };
227
371
  } else {
228
- throw new Error(`what is not a file nor symlink nor directory? nothing we care about: ${canonicalPath}`);
372
+ throw new Error(
373
+ `what is not a file nor symlink nor directory? nothing we care about: ${canonicalPath}`
374
+ );
229
375
  }
230
376
  if (!parent && node.type === "dir") {
231
377
  this.#trees.set(canonicalPath, node);
232
378
  return node;
233
379
  } else if (parent) {
234
- parent.dir.set(path3.basename(canonicalPath), node);
380
+ parent.dir.set(path.basename(canonicalPath), node);
235
381
  } else {
236
- throw new Error(`root can only be a dir, got ${JSON.stringify(node)} for path: ${canonicalPath}`);
382
+ throw new Error(
383
+ `root can only be a dir, got ${JSON.stringify(node)} for path: ${canonicalPath}`
384
+ );
237
385
  }
238
386
  return node;
239
387
  }
@@ -242,13 +390,13 @@ var CachingHost = class {
242
390
  * You should check the `fullPath` of the result.
243
391
  */
244
392
  #getNearestAncestorNode(filePath) {
245
- const canonicalPath = path3.resolve(filePath);
246
- const { root } = path3.parse(canonicalPath);
393
+ const canonicalPath = path.resolve(filePath);
394
+ const { root } = path.parse(canonicalPath);
247
395
  const parts = [];
248
396
  let maybePath = canonicalPath;
249
397
  while (maybePath !== root) {
250
- parts.unshift(path3.basename(maybePath));
251
- maybePath = path3.dirname(maybePath);
398
+ parts.unshift(path.basename(maybePath));
399
+ maybePath = path.dirname(maybePath);
252
400
  }
253
401
  let curPath = root;
254
402
  let curNode = this.#trees.get(root) ?? this.#stubify(curPath, void 0);
@@ -257,7 +405,9 @@ var CachingHost = class {
257
405
  assertNoTombstone(curNode);
258
406
  assertNotType(curNode, "file");
259
407
  if (curNode.type === "symlink") {
260
- const linkedNode = this.#getNodeResolvingSymlinks(path3.resolve(path3.dirname(curPath), curNode.symlink));
408
+ const linkedNode = this.#getNodeResolvingSymlinks(
409
+ path.resolve(path.dirname(curPath), curNode.symlink)
410
+ );
261
411
  assertExists(linkedNode);
262
412
  assertNoTombstone(linkedNode);
263
413
  assertType(linkedNode, "dir");
@@ -265,16 +415,18 @@ var CachingHost = class {
265
415
  }
266
416
  assertType(curNode, "dir");
267
417
  assertNoTombstone(curNode);
268
- curNode = curNode.dir.get(part) ?? this.#stubify(path3.join(curNode.fullPath, part), curNode);
269
- curPath = path3.join(curPath, part);
418
+ curNode = curNode.dir.get(part) ?? this.#stubify(path.join(curNode.fullPath, part), curNode);
419
+ curPath = path.join(curPath, part);
270
420
  }
271
421
  } catch (e) {
272
422
  }
273
423
  return { pathWithSymlinks: curPath, node: curNode };
274
424
  }
275
425
  #getNode(filePath) {
276
- const canonicalPath = path3.resolve(filePath);
277
- const { pathWithSymlinks, node } = this.#getNearestAncestorNode(canonicalPath);
426
+ const canonicalPath = path.resolve(filePath);
427
+ const { pathWithSymlinks, node } = this.#getNearestAncestorNode(
428
+ canonicalPath
429
+ );
278
430
  if (pathWithSymlinks === canonicalPath) {
279
431
  return node;
280
432
  }
@@ -287,16 +439,18 @@ var CachingHost = class {
287
439
  return this.#getNodeResolvingSymlinks(node.symlink, follows--);
288
440
  }
289
441
  mkdir(filePath, opts = { recursive: false }) {
290
- const canonicalPath = path3.resolve(filePath);
291
- const { node, pathWithSymlinks } = this.#getNearestAncestorNode(canonicalPath);
442
+ const canonicalPath = path.resolve(filePath);
443
+ const { node, pathWithSymlinks } = this.#getNearestAncestorNode(
444
+ canonicalPath
445
+ );
292
446
  if (filePath === pathWithSymlinks) {
293
447
  assertType(node, "dir");
294
448
  assertHasParent(node);
295
449
  if (!node.tombstone) return;
296
- } else if (path3.dirname(filePath) === pathWithSymlinks) {
450
+ } else if (path.dirname(filePath) === pathWithSymlinks) {
297
451
  assertType(node, "dir");
298
452
  assertNoTombstone(node);
299
- node.dir.set(path3.basename(filePath), {
453
+ node.dir.set(path.basename(filePath), {
300
454
  type: "dir",
301
455
  fullPath: filePath,
302
456
  parent: node,
@@ -305,15 +459,17 @@ var CachingHost = class {
305
459
  });
306
460
  return;
307
461
  }
308
- if (!opts.recursive && path3.dirname(canonicalPath) !== pathWithSymlinks) {
462
+ if (!opts.recursive && path.dirname(canonicalPath) !== pathWithSymlinks) {
309
463
  throw new Error("no such file or directory");
310
464
  }
311
465
  const rootPath = pathWithSymlinks;
312
466
  let maybePath = canonicalPath;
313
467
  const toMake = [];
314
468
  while (maybePath !== rootPath) {
315
- toMake.unshift(path3.resolve(node.fullPath, path3.relative(rootPath, maybePath)));
316
- maybePath = path3.dirname(maybePath);
469
+ toMake.unshift(
470
+ path.resolve(node.fullPath, path.relative(rootPath, maybePath))
471
+ );
472
+ maybePath = path.dirname(maybePath);
317
473
  }
318
474
  for (const dirToMake of toMake) {
319
475
  this.mkdir(dirToMake);
@@ -366,7 +522,7 @@ var CachingHost = class {
366
522
  }
367
523
  writeFile(filePath, body, opts) {
368
524
  const fileContentsAsBuffer = typeof body === "string" ? Buffer.from(body, opts == null ? void 0 : opts.encoding) : Buffer.from(body);
369
- const canonicalPath = path3.resolve(filePath);
525
+ const canonicalPath = path.resolve(filePath);
370
526
  const existingNode = this.#getNodeResolvingSymlinks(canonicalPath);
371
527
  if (existingNode) {
372
528
  if (existingNode.type === "dir") {
@@ -379,11 +535,13 @@ var CachingHost = class {
379
535
  });
380
536
  return;
381
537
  }
382
- const maybeDirNode = this.#getNodeResolvingSymlinks(path3.dirname(canonicalPath));
538
+ const maybeDirNode = this.#getNodeResolvingSymlinks(
539
+ path.dirname(canonicalPath)
540
+ );
383
541
  assertExists(maybeDirNode);
384
542
  assertType(maybeDirNode, "dir");
385
543
  assertNoTombstone(maybeDirNode);
386
- maybeDirNode.dir.set(path3.basename(canonicalPath), {
544
+ maybeDirNode.dir.set(path.basename(canonicalPath), {
387
545
  type: "file",
388
546
  fullPath: canonicalPath,
389
547
  parent: maybeDirNode,
@@ -392,7 +550,7 @@ var CachingHost = class {
392
550
  });
393
551
  }
394
552
  deleteFile(filePath) {
395
- const canonicalPath = path3.resolve(filePath);
553
+ const canonicalPath = path.resolve(filePath);
396
554
  const node = this.#getNode(canonicalPath);
397
555
  if (!node || node.type === "file" && node.tombstone === true) return;
398
556
  assertNotType(node, "dir");
@@ -427,265 +585,167 @@ var CachingHost = class {
427
585
  async #flushSymlinkNode(node) {
428
586
  if (!node.needsFlush) return;
429
587
  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;
588
+ const linkValue = await this.fs.promises.readlink(node.fullPath);
589
+ if (linkValue === node.symlink) {
590
+ return;
627
591
  }
628
- rowText.trim();
629
- console.log(rowText);
592
+ } catch (e) {
630
593
  }
631
- if (this.#config.showFooter) this.#printFooterRow();
632
- console.log();
594
+ return this.fs.promises.symlink(node.symlink, node.fullPath);
633
595
  }
634
- #getCellValueAsString(value, config) {
635
- if (config.type === "bigint" && config.renderAs === "nanoseconds") {
636
- return nanosecondsToSanity(value, config.precision ?? 9);
637
- } else {
638
- return "" + value;
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
+ }
639
603
  }
640
- }
641
- #getCellValueAligned(value, config, column) {
642
- let result;
643
- if (config.type === "bigint" && config.renderAs === "nanoseconds") {
644
- result = nanosecondsToSanity(value, config.precision ?? 9);
645
- } else {
646
- result = "" + value;
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
+ }
647
620
  }
648
- if (config.alignment === "left") {
649
- return result.padEnd(this.#columnWidths[column]);
650
- } else {
651
- return result.padStart(this.#columnWidths[column]);
621
+ await Promise.all(promises2);
622
+ if (node.tombstone) {
623
+ return this.fs.promises.rmdir(node.fullPath);
652
624
  }
625
+ return;
653
626
  }
654
- getEntryAsString(colNum, rowNum) {
655
- const config = this.#config.columns[colNum];
656
- if (config.type === "bigint" && config.renderAs === "nanoseconds") {
657
- return nanosecondsToSanity(this.#rows[rowNum][colNum], config.precision ?? 9);
658
- } else {
659
- return "" + this.#rows[rowNum][colNum];
627
+ flush() {
628
+ const promises2 = [];
629
+ for (const rootNode of this.#trees.values()) {
630
+ promises2.push(this.#flushDirNode(rootNode));
660
631
  }
632
+ return Promise.all(promises2);
661
633
  }
662
- getEntryAsStringAligned(colNum, rowNum) {
663
- const config = this.#config.columns[colNum];
664
- let result;
665
- if (config.type === "bigint" && config.renderAs === "nanoseconds") {
666
- result = nanosecondsToSanity(this.#rows[rowNum][colNum], config.precision ?? 9);
667
- } else {
668
- result = "" + this.#rows[rowNum][colNum];
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;
669
656
  }
670
- if (config.alignment === "left") {
671
- return result.padEnd(this.#columnWidths[colNum]);
672
- } else {
673
- return result.padStart(this.#columnWidths[colNum]);
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);
674
697
  }
698
+ return workspacePackages.map((project) => project.dir).filter(
699
+ (d) => d !== workspaceDir
700
+ );
675
701
  }
676
- getColumnWidth(colNum, config) {
677
- let maxWidth = Math.max(
678
- (config.header ?? "").length,
679
- 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."
680
705
  );
681
- for (let r = 0; r < this.#rows.length; r++) {
682
- maxWidth = Math.max(maxWidth, this.getEntryAsString(colNum, r).length);
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
+ }
683
723
  }
684
- return maxWidth;
685
724
  }
686
- };
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
+ }
687
746
 
688
747
  // src/matchesAnyGlob.ts
748
+ import micromatch from "micromatch";
689
749
  var cache = /* @__PURE__ */ new Map();
690
750
  var singleMatcherCache = /* @__PURE__ */ new Map();
691
751
  var compiledGlobCache = /* @__PURE__ */ new Map();
@@ -755,63 +815,53 @@ matchesAnyGlob.printStats = () => {
755
815
  table.print();
756
816
  };
757
817
 
758
- // src/AggregateTiming.ts
759
- var AggregateTiming = class {
760
- constructor(title) {
761
- this.title = title;
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;
762
830
  }
763
- #data = /* @__PURE__ */ new Map();
764
- #last;
765
- start(name) {
766
- const time = process.hrtime.bigint();
767
- if (this.#last) {
768
- this.#last.total += time;
769
- }
770
- let data = this.#data.get(name);
771
- if (data === void 0) {
772
- data = { count: 1, total: -time };
773
- this.#data.set(name, data);
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 });
774
843
  } else {
775
- data.total -= time;
776
- data.count++;
844
+ this.fs.writeFileSync(path4, body);
777
845
  }
778
- this.#last = data;
779
846
  }
780
- stop() {
781
- const time = process.hrtime.bigint();
782
- if (this.#last) {
783
- this.#last.total += time;
784
- 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"));
785
850
  }
851
+ return this.fs.readFileSync(path4, opts == null ? void 0 : opts.encoding);
786
852
  }
787
- printResults() {
788
- const table = new Table({
789
- sortColumn: -1,
790
- showFooter: true,
791
- showHeader: true,
792
- title: this.title,
793
- columns: [
794
- {
795
- header: "Duration",
796
- type: "bigint",
797
- renderAs: "nanoseconds",
798
- footer: { aggregate: "sum" }
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();
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();
815
865
  }
816
866
  };
817
867
 
@@ -871,13 +921,13 @@ export {
871
921
  nanosecondsToSanity
872
922
  };
873
923
  /*!
874
- * Copyright 2019 Palantir Technologies, Inc.
924
+ * Copyright 2022 Palantir Technologies, Inc.
875
925
  *
876
926
  * Licensed under the MIT license. See LICENSE file in the project root for details.
877
927
  *
878
928
  */
879
929
  /*!
880
- * Copyright 2022 Palantir Technologies, Inc.
930
+ * Copyright 2019 Palantir Technologies, Inc.
881
931
  *
882
932
  * Licensed under the MIT license. See LICENSE file in the project root for details.
883
933
  *