@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.
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 +11 -10
  5. package/.turbo/turbo-transpile-typescript.log +4 -4
  6. package/CHANGELOG.md +4 -0
  7. package/build/js/index.js +489 -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 +252 -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 +137 -29
  29. package/coverage/Timing.ts.html +1 -1
  30. package/coverage/clover.xml +527 -396
  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 +168 -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 +104 -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 +58 -22
  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 +19 -9
  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 +6 -7
  56. package/vitest.config.mjs.timestamp-1736878329730-aa478e2241542.mjs +2 -2
@@ -6,10 +6,12 @@
6
6
  */
7
7
 
8
8
  import * as realFs from "node:fs";
9
- import { Host } from "./Host.js";
10
9
  import * as path from "node:path";
10
+ import { Host } from "./Host.js";
11
11
 
12
- function assertNoTombstone(node: Node): asserts node is Node & { tombstone?: false } {
12
+ function assertNoTombstone(
13
+ node: Node,
14
+ ): asserts node is Node & { tombstone?: false } {
13
15
  if (node.tombstone) {
14
16
  throw new Error(`Unexpected tombstone ${JSON.stringify(node)}`);
15
17
  }
@@ -17,14 +19,17 @@ function assertNoTombstone(node: Node): asserts node is Node & { tombstone?: fal
17
19
 
18
20
  function assertNotType<N extends Node, T extends Node["type"]>(
19
21
  node: N,
20
- type: T
22
+ type: T,
21
23
  ): asserts node is N & { type: Exclude<N["type"], T> } {
22
24
  if (node.type === type) {
23
25
  throw new Error(`Unexpected node type ${JSON.stringify(node)}`);
24
26
  }
25
27
  }
26
28
 
27
- function assertType<N extends Node, T extends Node["type"]>(node: N, type: T): asserts node is N & { type: T } {
29
+ function assertType<N extends Node, T extends Node["type"]>(
30
+ node: N,
31
+ type: T,
32
+ ): asserts node is N & { type: T } {
28
33
  if (node.type !== type) {
29
34
  throw new Error(`Unexpected node type ${JSON.stringify(node)}`);
30
35
  }
@@ -90,7 +95,14 @@ interface SymlinkNode extends BaseNode<"symlink"> {
90
95
  symlink: string;
91
96
  }
92
97
 
93
- type Node = DirNode | FileNode | SymlinkNode | DirTombstoneNode | FileTombstoneNode | DirStubNode | FileStubNode;
98
+ type Node =
99
+ | DirNode
100
+ | FileNode
101
+ | SymlinkNode
102
+ | DirTombstoneNode
103
+ | FileTombstoneNode
104
+ | DirStubNode
105
+ | FileStubNode;
94
106
 
95
107
  export class CachingHost implements Host {
96
108
  // We need many trees because of windows, key is the `root`
@@ -111,23 +123,29 @@ export class CachingHost implements Host {
111
123
  | "statSync"
112
124
  | "unlinkSync"
113
125
  | "writeFileSync"
114
- > = realFs
126
+ > = realFs,
115
127
  ) {}
116
128
 
117
129
  #replaceNode(
118
130
  node: FileNode | FileStubNode | SymlinkNode,
119
- newNode: Omit<FileTombstoneNode, "fullPath" | "parent">
131
+ newNode: Omit<FileTombstoneNode, "fullPath" | "parent">,
120
132
  ): FileTombstoneNode;
121
133
  #replaceNode(
122
134
  node: FileNode | FileStubNode | FileTombstoneNode,
123
- newNode: Omit<FileNode, "fullPath" | "parent">
135
+ newNode: Omit<FileNode, "fullPath" | "parent">,
124
136
  ): FileNode;
125
137
  #replaceNode(
126
138
  node: DirTombstoneNode | DirStubNode,
127
- newNode: Omit<DirNode, "fullPath" | "parent" | "dir">
139
+ newNode: Omit<DirNode, "fullPath" | "parent" | "dir">,
128
140
  ): DirStubNode;
129
- #replaceNode(node: DirNode, newNode: Omit<DirTombstoneNode, "fullPath" | "parent" | "dir">): DirTombstoneNode;
130
- #replaceNode(node: Node, partialNewNode: Omit<Node, "fullPath" | "parent">): Node {
141
+ #replaceNode(
142
+ node: DirNode,
143
+ newNode: Omit<DirTombstoneNode, "fullPath" | "parent" | "dir">,
144
+ ): DirTombstoneNode;
145
+ #replaceNode(
146
+ node: Node,
147
+ partialNewNode: Omit<Node, "fullPath" | "parent">,
148
+ ): Node {
131
149
  if (!node.parent) throw new Error("Cannot replace root node");
132
150
  const newNode: Node = {
133
151
  ...partialNewNode,
@@ -156,15 +174,22 @@ export class CachingHost implements Host {
156
174
  * Throws if the path doesnt exist!
157
175
  */
158
176
  #stubify(filePath: string, parent: undefined): DirStubNode;
159
- #stubify(filePath: string, parent: DirNode | DirStubNode | undefined): DirStubNode | SymlinkNode | FileStubNode;
160
177
  #stubify(
161
178
  filePath: string,
162
- parent: DirNode | DirStubNode | undefined
163
- ): typeof parent extends undefined ? DirNode | DirStubNode : DirNode | DirStubNode | SymlinkNode | FileStubNode {
179
+ parent: DirNode | DirStubNode | undefined,
180
+ ): DirStubNode | SymlinkNode | FileStubNode;
181
+ #stubify(
182
+ filePath: string,
183
+ parent: DirNode | DirStubNode | undefined,
184
+ ): typeof parent extends undefined ? DirNode | DirStubNode
185
+ : DirNode | DirStubNode | SymlinkNode | FileStubNode
186
+ {
164
187
  const canonicalPath = path.resolve(filePath);
165
188
 
166
189
  if (!parent && canonicalPath !== path.parse(canonicalPath).root) {
167
- throw new Error(`parent can only be null if path is root. Instead got: ${canonicalPath}`);
190
+ throw new Error(
191
+ `parent can only be null if path is root. Instead got: ${canonicalPath}`,
192
+ );
168
193
  }
169
194
  const stat = this.fs.lstatSync(canonicalPath); // may throw
170
195
 
@@ -196,7 +221,9 @@ export class CachingHost implements Host {
196
221
  needsFlush: false,
197
222
  };
198
223
  } else {
199
- throw new Error(`what is not a file nor symlink nor directory? nothing we care about: ${canonicalPath}`);
224
+ throw new Error(
225
+ `what is not a file nor symlink nor directory? nothing we care about: ${canonicalPath}`,
226
+ );
200
227
  }
201
228
 
202
229
  if (!parent && node.type === "dir") {
@@ -205,7 +232,9 @@ export class CachingHost implements Host {
205
232
  } else if (parent) {
206
233
  parent.dir.set(path.basename(canonicalPath), node);
207
234
  } else {
208
- throw new Error(`root can only be a dir, got ${JSON.stringify(node)} for path: ${canonicalPath}`);
235
+ throw new Error(
236
+ `root can only be a dir, got ${JSON.stringify(node)} for path: ${canonicalPath}`,
237
+ );
209
238
  }
210
239
  return node;
211
240
  }
@@ -226,13 +255,16 @@ export class CachingHost implements Host {
226
255
  }
227
256
 
228
257
  let curPath = root;
229
- let curNode: Node = this.#trees.get(root) ?? this.#stubify(curPath, undefined); // its okay to throw if there is no root
258
+ let curNode: Node = this.#trees.get(root)
259
+ ?? this.#stubify(curPath, undefined); // its okay to throw if there is no root
230
260
  try {
231
261
  for (const part of parts) {
232
262
  assertNoTombstone(curNode);
233
263
  assertNotType(curNode, "file");
234
264
  if (curNode.type === "symlink") {
235
- const linkedNode = this.#getNodeResolvingSymlinks(path.resolve(path.dirname(curPath), curNode.symlink));
265
+ const linkedNode = this.#getNodeResolvingSymlinks(
266
+ path.resolve(path.dirname(curPath), curNode.symlink),
267
+ );
236
268
  assertExists(linkedNode);
237
269
  assertNoTombstone(linkedNode);
238
270
  assertType(linkedNode, "dir");
@@ -240,7 +272,8 @@ export class CachingHost implements Host {
240
272
  }
241
273
  assertType(curNode, "dir");
242
274
  assertNoTombstone(curNode);
243
- curNode = curNode.dir.get(part) ?? this.#stubify(path.join(curNode.fullPath, part), curNode);
275
+ curNode = curNode.dir.get(part)
276
+ ?? this.#stubify(path.join(curNode.fullPath, part), curNode);
244
277
  curPath = path.join(curPath, part);
245
278
  }
246
279
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
@@ -253,14 +286,19 @@ export class CachingHost implements Host {
253
286
 
254
287
  #getNode(filePath: string) {
255
288
  const canonicalPath = path.resolve(filePath);
256
- const { pathWithSymlinks, node } = this.#getNearestAncestorNode(canonicalPath);
289
+ const { pathWithSymlinks, node } = this.#getNearestAncestorNode(
290
+ canonicalPath,
291
+ );
257
292
  if (pathWithSymlinks === canonicalPath) {
258
293
  return node;
259
294
  }
260
295
  return undefined;
261
296
  }
262
297
 
263
- #getNodeResolvingSymlinks(filePath: string, follows: number = 100): Exclude<Node, SymlinkNode> | undefined {
298
+ #getNodeResolvingSymlinks(
299
+ filePath: string,
300
+ follows: number = 100,
301
+ ): Exclude<Node, SymlinkNode> | undefined {
264
302
  const node = this.#getNode(filePath); // canonicalizes for us
265
303
  if (!node || node.type !== "symlink") return node;
266
304
  // this is a really poor mans way of doing this. but who has 100's of symlinks hanging around?
@@ -269,9 +307,14 @@ export class CachingHost implements Host {
269
307
  return this.#getNodeResolvingSymlinks(node.symlink, follows--);
270
308
  }
271
309
 
272
- mkdir(filePath: string, opts: { recursive: boolean } = { recursive: false }): void {
310
+ mkdir(
311
+ filePath: string,
312
+ opts: { recursive: boolean } = { recursive: false },
313
+ ): void {
273
314
  const canonicalPath = path.resolve(filePath);
274
- const { node, pathWithSymlinks } = this.#getNearestAncestorNode(canonicalPath);
315
+ const { node, pathWithSymlinks } = this.#getNearestAncestorNode(
316
+ canonicalPath,
317
+ );
275
318
  if (filePath === pathWithSymlinks) {
276
319
  assertType(node, "dir");
277
320
  assertHasParent(node);
@@ -297,7 +340,9 @@ export class CachingHost implements Host {
297
340
  let maybePath = canonicalPath;
298
341
  const toMake: string[] = [];
299
342
  while (maybePath !== rootPath) {
300
- toMake.unshift(path.resolve(node.fullPath, path.relative(rootPath, maybePath)));
343
+ toMake.unshift(
344
+ path.resolve(node.fullPath, path.relative(rootPath, maybePath)),
345
+ );
301
346
  maybePath = path.dirname(maybePath);
302
347
  }
303
348
 
@@ -337,7 +382,10 @@ export class CachingHost implements Host {
337
382
  readFile(filePath: string, opts: { asJson: true }): object;
338
383
  readFile(
339
384
  filePath: string,
340
- opts: undefined | { encoding: BufferEncoding; asJson?: false } | { encoding?: never; asJson: true }
385
+ opts: undefined | { encoding: BufferEncoding; asJson?: false } | {
386
+ encoding?: never;
387
+ asJson: true;
388
+ },
341
389
  ) {
342
390
  let node = this.#getNodeResolvingSymlinks(filePath); // canonicalizes for us
343
391
 
@@ -365,10 +413,24 @@ export class CachingHost implements Host {
365
413
  }
366
414
 
367
415
  writeFile(filePath: string, buffer: Buffer): void;
368
- writeFile(filePath: string, body: string, opts: { encoding: BufferEncoding }): void;
369
- writeFile(filePath: string, body: string, opts: { encoding: BufferEncoding }): void;
370
- writeFile(filePath: string, body: string | Buffer, opts?: { encoding: BufferEncoding }) {
371
- const fileContentsAsBuffer = typeof body === "string" ? Buffer.from(body, opts?.encoding) : Buffer.from(body);
416
+ writeFile(
417
+ filePath: string,
418
+ body: string,
419
+ opts: { encoding: BufferEncoding },
420
+ ): void;
421
+ writeFile(
422
+ filePath: string,
423
+ body: string,
424
+ opts: { encoding: BufferEncoding },
425
+ ): void;
426
+ writeFile(
427
+ filePath: string,
428
+ body: string | Buffer,
429
+ opts?: { encoding: BufferEncoding },
430
+ ) {
431
+ const fileContentsAsBuffer = typeof body === "string"
432
+ ? Buffer.from(body, opts?.encoding)
433
+ : Buffer.from(body);
372
434
 
373
435
  const canonicalPath = path.resolve(filePath);
374
436
  const existingNode = this.#getNodeResolvingSymlinks(canonicalPath);
@@ -384,7 +446,9 @@ export class CachingHost implements Host {
384
446
  return;
385
447
  }
386
448
 
387
- const maybeDirNode = this.#getNodeResolvingSymlinks(path.dirname(canonicalPath));
449
+ const maybeDirNode = this.#getNodeResolvingSymlinks(
450
+ path.dirname(canonicalPath),
451
+ );
388
452
  assertExists(maybeDirNode);
389
453
  assertType(maybeDirNode, "dir");
390
454
  assertNoTombstone(maybeDirNode);
@@ -420,7 +484,9 @@ export class CachingHost implements Host {
420
484
  });
421
485
  }
422
486
 
423
- async #flushFileNode(node: FileNode | FileStubNode | FileTombstoneNode): Promise<unknown> {
487
+ async #flushFileNode(
488
+ node: FileNode | FileStubNode | FileTombstoneNode,
489
+ ): Promise<unknown> {
424
490
  // FIXME all tombstones need a flush, so we can get rid of needsFlush for them
425
491
  if (node.tombstone) {
426
492
  try {
@@ -453,7 +519,9 @@ export class CachingHost implements Host {
453
519
  return this.fs.promises.symlink(node.symlink, node.fullPath);
454
520
  }
455
521
 
456
- async #flushDirNode(node: DirNode | DirStubNode | DirTombstoneNode): Promise<unknown> {
522
+ async #flushDirNode(
523
+ node: DirNode | DirStubNode | DirTombstoneNode,
524
+ ): Promise<unknown> {
457
525
  if (!node.tombstone && node.needsFlush) {
458
526
  try {
459
527
  await this.fs.promises.access(node.fullPath); // throws if the file doesnt exist
@@ -466,7 +534,9 @@ export class CachingHost implements Host {
466
534
  const promises: Promise<unknown>[] = [];
467
535
  for (const child of node.dir.values()) {
468
536
  if (node.tombstone && !child.tombstone) {
469
- throw new Error("Unexpected failure during sanity check. A non-deleted child is on a deleted dir");
537
+ throw new Error(
538
+ "Unexpected failure during sanity check. A non-deleted child is on a deleted dir",
539
+ );
470
540
  }
471
541
  if (child.type === "dir") {
472
542
  promises.push(this.#flushDirNode(child));
package/src/Host.ts CHANGED
@@ -19,7 +19,11 @@ export interface Host {
19
19
  writeJson(path: string, o: object): void;
20
20
 
21
21
  writeFile(path: string, buffer: Buffer): void;
22
- writeFile(path: string, body: string, opts: { encoding: BufferEncoding }): void;
22
+ writeFile(
23
+ path: string,
24
+ body: string,
25
+ opts: { encoding: BufferEncoding },
26
+ ): void;
23
27
 
24
28
  readFile(path: string, opts?: undefined): Buffer;
25
29
  readFile(path: string, opts: { encoding: BufferEncoding }): string;
@@ -14,9 +14,9 @@ export interface PackageJson {
14
14
  optionalDependencies?: Record<string, string>;
15
15
  workspaces?:
16
16
  | {
17
- packages?: string[];
18
- nohoist?: string[];
19
- }
17
+ packages?: string[];
18
+ nohoist?: string[];
19
+ }
20
20
  | string[];
21
21
  [otherKey: string]: unknown;
22
22
  }
package/src/SimpleHost.ts CHANGED
@@ -22,8 +22,16 @@ export class SimpleHost implements Host {
22
22
  }
23
23
 
24
24
  writeFile(path: string, buffer: Buffer): void;
25
- writeFile(path: string, body: string, opts: { encoding: BufferEncoding }): void;
26
- writeFile(path: string, body: string | Buffer, opts?: { encoding: BufferEncoding }): void {
25
+ writeFile(
26
+ path: string,
27
+ body: string,
28
+ opts: { encoding: BufferEncoding },
29
+ ): void;
30
+ writeFile(
31
+ path: string,
32
+ body: string | Buffer,
33
+ opts?: { encoding: BufferEncoding },
34
+ ): void {
27
35
  if (opts) {
28
36
  this.fs.writeFileSync(path, body, { encoding: opts.encoding });
29
37
  } else {
@@ -33,7 +41,10 @@ export class SimpleHost implements Host {
33
41
  readFile(path: string, opts?: undefined): Buffer;
34
42
  readFile(path: string, opts: { encoding: BufferEncoding }): string;
35
43
  readFile(path: string, opts: { asJson: true }): object;
36
- readFile(path: string, opts?: { encoding?: BufferEncoding; asJson?: boolean }): string | object | Buffer {
44
+ readFile(
45
+ path: string,
46
+ opts?: { encoding?: BufferEncoding; asJson?: boolean },
47
+ ): string | object | Buffer {
37
48
  if (opts?.asJson) {
38
49
  return JSON.parse(this.fs.readFileSync(path, "utf-8"));
39
50
  }
package/src/Table.ts CHANGED
@@ -6,8 +6,9 @@
6
6
  */
7
7
  // tslint:disable:no-console
8
8
  import { nanosecondsToSanity } from "./nanosecondsToSanity.js";
9
- type HeaderFooterHelper<HB, FB, H, F> = (HB extends true ? { header: H } : { header?: H }) &
10
- (FB extends true ? { footer: F } : { footer?: F });
9
+ type HeaderFooterHelper<HB, FB, H, F> =
10
+ & (HB extends true ? { header: H } : { header?: H })
11
+ & (FB extends true ? { footer: F } : { footer?: F });
11
12
 
12
13
  type WithAlignemnt = { alignment?: "right" | "left" };
13
14
  type BaseCellConfig = WithAlignemnt & { type: "bigint" | "string" };
@@ -19,13 +20,20 @@ type BaseBigIntCellConfig = {
19
20
  } & WithAlignemnt;
20
21
  type BaseStringCellConfig = { type: "string" } & WithAlignemnt;
21
22
 
22
- type BigIntColumnConfig<H, F> = WithAlignemnt &
23
- BaseBigIntCellConfig &
24
- HeaderFooterHelper<H, F, string, AggregateFooterConfig | StaticFooterConfig>;
25
-
26
- type StringColumnConfig<H, F> = WithAlignemnt &
27
- BaseStringCellConfig &
28
- HeaderFooterHelper<H, F, string, StaticFooterConfig>;
23
+ type BigIntColumnConfig<H, F> =
24
+ & WithAlignemnt
25
+ & BaseBigIntCellConfig
26
+ & HeaderFooterHelper<
27
+ H,
28
+ F,
29
+ string,
30
+ AggregateFooterConfig | StaticFooterConfig
31
+ >;
32
+
33
+ type StringColumnConfig<H, F> =
34
+ & WithAlignemnt
35
+ & BaseStringCellConfig
36
+ & HeaderFooterHelper<H, F, string, StaticFooterConfig>;
29
37
 
30
38
  type AggregateFooterConfig = {
31
39
  aggregate: "sum" | "average";
@@ -47,7 +55,8 @@ type TableConfig<T extends any[], H extends boolean, F extends boolean> = {
47
55
  showHeader: H;
48
56
  showFooter: F;
49
57
  columns: {
50
- [K in keyof T]: T[K] extends bigint ? BigIntColumnConfig<H, F> : StringColumnConfig<H, F>;
58
+ [K in keyof T]: T[K] extends bigint ? BigIntColumnConfig<H, F>
59
+ : StringColumnConfig<H, F>;
51
60
  };
52
61
  title: string;
53
62
  };
@@ -74,7 +83,7 @@ export class Table<T extends any[]> {
74
83
  | TableConfig<T, true, true>
75
84
  | TableConfig<T, true, false>
76
85
  | TableConfig<T, false, true>
77
- | TableConfig<T, false, false>
86
+ | TableConfig<T, false, false>,
78
87
  ) {
79
88
  this.#config = {
80
89
  padding: 2,
@@ -101,7 +110,9 @@ export class Table<T extends any[]> {
101
110
  ...columnConfig.footer,
102
111
  });
103
112
  } else if ("aggregate" in columnConfig.footer) {
104
- if (columnConfig.type !== "bigint") throw new Error("expecting bigint for aggregate");
113
+ if (columnConfig.type !== "bigint") {
114
+ throw new Error("expecting bigint for aggregate");
115
+ }
105
116
  this.#footerRowConfig.push({
106
117
  type: columnConfig.type,
107
118
  renderAs: columnConfig.renderAs,
@@ -157,8 +168,11 @@ export class Table<T extends any[]> {
157
168
  (this.#config.columns[c].header ?? "").length,
158
169
  ...this.#rows.map((a) => this.#getCellValueAsString(a[c], colConfig).length),
159
170
  this.#footer && this.#footerRowConfig
160
- ? this.#getCellValueAsString(this.#footer?.[c] ?? "", this.#footerRowConfig[c]).length
161
- : 0
171
+ ? this.#getCellValueAsString(
172
+ this.#footer?.[c] ?? "",
173
+ this.#footerRowConfig[c],
174
+ ).length
175
+ : 0,
162
176
  );
163
177
  }
164
178
 
@@ -208,7 +222,8 @@ export class Table<T extends any[]> {
208
222
 
209
223
  let hr = "";
210
224
  for (let c = 0; c < footerRow.length; c++) {
211
- hr += this.#getCellValueAligned(footerRow[c], this.#footerRowConfig![c], c) + paddingString; // .padEnd(this.#columnWidths[c], " ") + paddingString;
225
+ hr += this.#getCellValueAligned(footerRow[c], this.#footerRowConfig![c], c)
226
+ + paddingString; // .padEnd(this.#columnWidths[c], " ") + paddingString;
212
227
  }
213
228
  hr = hr.trimRight();
214
229
  console.log(hr);
@@ -246,7 +261,10 @@ export class Table<T extends any[]> {
246
261
  console.log();
247
262
  }
248
263
 
249
- #getCellValueAsString(value: bigint | string, config: BaseBigIntCellConfig | BaseStringCellConfig) {
264
+ #getCellValueAsString(
265
+ value: bigint | string,
266
+ config: BaseBigIntCellConfig | BaseStringCellConfig,
267
+ ) {
250
268
  if (config.type === "bigint" && config.renderAs === "nanoseconds") {
251
269
  return nanosecondsToSanity(value as bigint, config.precision ?? 9);
252
270
  } else {
@@ -254,7 +272,11 @@ export class Table<T extends any[]> {
254
272
  }
255
273
  }
256
274
 
257
- #getCellValueAligned(value: bigint | string, config: BaseBigIntCellConfig | BaseStringCellConfig, column: number) {
275
+ #getCellValueAligned(
276
+ value: bigint | string,
277
+ config: BaseBigIntCellConfig | BaseStringCellConfig,
278
+ column: number,
279
+ ) {
258
280
  let result: string;
259
281
  if (config.type === "bigint" && config.renderAs === "nanoseconds") {
260
282
  result = nanosecondsToSanity(value as bigint, config.precision ?? 9);
@@ -273,7 +295,10 @@ export class Table<T extends any[]> {
273
295
  const config = this.#config.columns[colNum];
274
296
 
275
297
  if (config.type === "bigint" && config.renderAs === "nanoseconds") {
276
- return nanosecondsToSanity(this.#rows[rowNum][colNum], config.precision ?? 9);
298
+ return nanosecondsToSanity(
299
+ this.#rows[rowNum][colNum],
300
+ config.precision ?? 9,
301
+ );
277
302
  } else {
278
303
  return "" + this.#rows[rowNum][colNum];
279
304
  }
@@ -284,7 +309,10 @@ export class Table<T extends any[]> {
284
309
 
285
310
  let result: string;
286
311
  if (config.type === "bigint" && config.renderAs === "nanoseconds") {
287
- result = nanosecondsToSanity(this.#rows[rowNum][colNum], config.precision ?? 9);
312
+ result = nanosecondsToSanity(
313
+ this.#rows[rowNum][colNum],
314
+ config.precision ?? 9,
315
+ );
288
316
  } else {
289
317
  result = "" + this.#rows[rowNum][colNum];
290
318
  }
@@ -296,12 +324,20 @@ export class Table<T extends any[]> {
296
324
  }
297
325
  }
298
326
 
299
- getColumnWidth(colNum: number, config: BigIntColumnConfig<boolean, boolean> | StringColumnConfig<boolean, boolean>) {
327
+ getColumnWidth(
328
+ colNum: number,
329
+ config:
330
+ | BigIntColumnConfig<boolean, boolean>
331
+ | StringColumnConfig<boolean, boolean>,
332
+ ) {
300
333
  let maxWidth = Math.max(
301
334
  (config.header ?? "").length,
302
335
  this.#footer && this.#footerRowConfig
303
- ? this.#getCellValueAsString(this.#footer[colNum], this.#footerRowConfig[colNum]).length
304
- : 0
336
+ ? this.#getCellValueAsString(
337
+ this.#footer[colNum],
338
+ this.#footerRowConfig[colNum],
339
+ ).length
340
+ : 0,
305
341
  );
306
342
 
307
343
  for (let r = 0; r < this.#rows.length; r++) {