@brianbuie/node-kit 0.12.3 → 0.12.5
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/README.md +88 -10
- package/dist/index.d.mts +36 -30
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +83 -41
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -1
- package/prettier.config.ts +1 -3
- package/src/Dir.ts +7 -3
- package/src/File.ts +42 -6
- package/src/Format.ts +29 -6
- package/src/Log.test.ts +0 -13
- package/src/Log.ts +32 -26
package/README.md
CHANGED
|
@@ -14,6 +14,35 @@ npm add @brianbuie/node-kit
|
|
|
14
14
|
import { Fetcher, Log } from '@brianbuie/node-kit';
|
|
15
15
|
```
|
|
16
16
|
|
|
17
|
+
# Extending Config
|
|
18
|
+
|
|
19
|
+
### tsconfig.json
|
|
20
|
+
|
|
21
|
+
```json
|
|
22
|
+
{
|
|
23
|
+
"extends": "./node_modules/@brianbuie/node-kit/tsconfig.json"
|
|
24
|
+
}
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### prettier.config.ts
|
|
28
|
+
|
|
29
|
+
```ts
|
|
30
|
+
export * from './node_modules/@brianbuie/node-kit/prettier.config.ts';
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Or make changes:
|
|
34
|
+
|
|
35
|
+
```ts
|
|
36
|
+
import baseConfig from './node_modules/@brianbuie/node-kit/prettier.config.ts';
|
|
37
|
+
|
|
38
|
+
const config = {
|
|
39
|
+
...baseConfig,
|
|
40
|
+
printWidth: 80,
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export default config;
|
|
44
|
+
```
|
|
45
|
+
|
|
17
46
|
# API
|
|
18
47
|
|
|
19
48
|
<!--#region ts2md-api-merged-here-->
|
|
@@ -394,9 +423,18 @@ A generic file adaptor, extended by specific file type implementations
|
|
|
394
423
|
export class FileType {
|
|
395
424
|
file;
|
|
396
425
|
constructor(filepath: string, contents?: string)
|
|
397
|
-
get exists()
|
|
398
426
|
get path()
|
|
427
|
+
get root()
|
|
428
|
+
get dir()
|
|
429
|
+
get base()
|
|
430
|
+
get name()
|
|
431
|
+
get ext()
|
|
432
|
+
get type()
|
|
433
|
+
get exists()
|
|
434
|
+
get stats()
|
|
399
435
|
delete()
|
|
436
|
+
get readStream()
|
|
437
|
+
get writeStream()
|
|
400
438
|
}
|
|
401
439
|
```
|
|
402
440
|
|
|
@@ -476,9 +514,10 @@ Helpers for formatting dates, times, and numbers as strings
|
|
|
476
514
|
|
|
477
515
|
```ts
|
|
478
516
|
export class Format {
|
|
479
|
-
static date(formatStr: "iso" | "ymd" | string = "iso", d: DateArg<Date> = new Date())
|
|
517
|
+
static date(formatStr: "iso" | "ymd" | "ymd-hm" | "ymd-hms" | "h:m:s" | string = "iso", d: DateArg<Date> = new Date())
|
|
480
518
|
static round(n: number, places = 0)
|
|
481
|
-
static
|
|
519
|
+
static plural(amount: number, singular: string, multiple?: string)
|
|
520
|
+
static ms(ms: number, style?: "digital")
|
|
482
521
|
static bytes(b: number)
|
|
483
522
|
}
|
|
484
523
|
```
|
|
@@ -492,22 +531,41 @@ export class Format {
|
|
|
492
531
|
date-fns format() with some shortcuts
|
|
493
532
|
|
|
494
533
|
```ts
|
|
495
|
-
static date(formatStr: "iso" | "ymd" | string = "iso", d: DateArg<Date> = new Date())
|
|
534
|
+
static date(formatStr: "iso" | "ymd" | "ymd-hm" | "ymd-hms" | "h:m:s" | string = "iso", d: DateArg<Date> = new Date())
|
|
496
535
|
```
|
|
497
536
|
|
|
498
537
|
Argument Details
|
|
499
538
|
|
|
500
539
|
+ **formatStr**
|
|
501
|
-
+
|
|
540
|
+
+ the format to use
|
|
541
|
+
+ **date**
|
|
542
|
+
+ the date to format, default `new Date()`
|
|
543
|
+
|
|
544
|
+
Example
|
|
545
|
+
|
|
546
|
+
```ts
|
|
547
|
+
Format.date('iso') // '2026-04-08T13:56:45Z'
|
|
548
|
+
Format.date('ymd') // '20260408'
|
|
549
|
+
Format.date('ymd-hm') // '20260408-1356'
|
|
550
|
+
Format.date('ymd-hms') // '20260408-135645'
|
|
551
|
+
Format.date('h:m:s') // '13:56:45'
|
|
552
|
+
```
|
|
502
553
|
|
|
503
554
|
### Method ms
|
|
504
555
|
|
|
505
556
|
Make millisecond durations actually readable (eg "123ms", "3.56s", "1m 34s", "3h 24m", "2d 4h")
|
|
506
557
|
|
|
507
558
|
```ts
|
|
508
|
-
static ms(ms: number)
|
|
559
|
+
static ms(ms: number, style?: "digital")
|
|
509
560
|
```
|
|
510
561
|
|
|
562
|
+
Argument Details
|
|
563
|
+
|
|
564
|
+
+ **ms**
|
|
565
|
+
+ milliseconds
|
|
566
|
+
+ **style**
|
|
567
|
+
+ 'digital' to output as 'HH:MM:SS'
|
|
568
|
+
|
|
511
569
|
### Method round
|
|
512
570
|
|
|
513
571
|
Round a number to a specific set of places
|
|
@@ -525,10 +583,10 @@ Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types
|
|
|
525
583
|
|
|
526
584
|
```ts
|
|
527
585
|
export class Log {
|
|
528
|
-
static
|
|
586
|
+
static getStack()
|
|
529
587
|
static #toGcloud(entry: Entry)
|
|
530
588
|
static #toConsole(entry: Entry, color: ChalkInstance)
|
|
531
|
-
static #log(
|
|
589
|
+
static #log({ severity, color }: Options, ...input: unknown[])
|
|
532
590
|
static prepare(...input: unknown[]): {
|
|
533
591
|
message?: string;
|
|
534
592
|
details: unknown[];
|
|
@@ -733,13 +791,33 @@ Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types
|
|
|
733
791
|
---
|
|
734
792
|
# Variables
|
|
735
793
|
|
|
794
|
+
| |
|
|
795
|
+
| --- |
|
|
796
|
+
| [cwd](#variable-cwd) |
|
|
797
|
+
| [temp](#variable-temp) |
|
|
798
|
+
|
|
799
|
+
Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types), [Variables](#variables)
|
|
800
|
+
|
|
801
|
+
---
|
|
802
|
+
|
|
803
|
+
## Variable: cwd
|
|
804
|
+
|
|
805
|
+
```ts
|
|
806
|
+
cwd = new Dir("./")
|
|
807
|
+
```
|
|
808
|
+
|
|
809
|
+
See also: [Dir](#class-dir)
|
|
810
|
+
|
|
811
|
+
Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types), [Variables](#variables)
|
|
812
|
+
|
|
813
|
+
---
|
|
736
814
|
## Variable: temp
|
|
737
815
|
|
|
738
816
|
```ts
|
|
739
|
-
temp =
|
|
817
|
+
temp = cwd.tempDir(".temp")
|
|
740
818
|
```
|
|
741
819
|
|
|
742
|
-
See also: [
|
|
820
|
+
See also: [cwd](#variable-cwd)
|
|
743
821
|
|
|
744
822
|
Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types), [Variables](#variables)
|
|
745
823
|
|
package/dist/index.d.mts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import * as fs from "node:fs";
|
|
2
2
|
import { Readable } from "node:stream";
|
|
3
3
|
import { DateArg, Duration } from "date-fns";
|
|
4
|
-
import { ChalkInstance } from "chalk";
|
|
5
4
|
import * as qt from "quicktype-core";
|
|
6
5
|
import * as quicktype_core_dist_TargetLanguage_js0 from "quicktype-core/dist/TargetLanguage.js";
|
|
7
6
|
import * as quicktype_core_dist_support_Comments_js0 from "quicktype-core/dist/support/Comments.js";
|
|
@@ -91,9 +90,18 @@ declare class File {
|
|
|
91
90
|
declare class FileType {
|
|
92
91
|
file: File;
|
|
93
92
|
constructor(filepath: string, contents?: string);
|
|
94
|
-
get exists(): boolean;
|
|
95
93
|
get path(): string;
|
|
94
|
+
get root(): string;
|
|
95
|
+
get dir(): string;
|
|
96
|
+
get base(): string;
|
|
97
|
+
get name(): string;
|
|
98
|
+
get ext(): string;
|
|
99
|
+
get type(): string | undefined;
|
|
100
|
+
get exists(): boolean;
|
|
101
|
+
get stats(): Partial<fs.Stats>;
|
|
96
102
|
delete(): void;
|
|
103
|
+
get readStream(): fs.ReadStream | Readable;
|
|
104
|
+
get writeStream(): fs.WriteStream;
|
|
97
105
|
}
|
|
98
106
|
/**
|
|
99
107
|
* A .json file that maintains data type when reading/writing.
|
|
@@ -187,7 +195,7 @@ declare class TempDir extends Dir {
|
|
|
187
195
|
clear(): void;
|
|
188
196
|
}
|
|
189
197
|
/**
|
|
190
|
-
*
|
|
198
|
+
* ./.temp in current working directory
|
|
191
199
|
*/
|
|
192
200
|
declare const temp: TempDir;
|
|
193
201
|
//#endregion
|
|
@@ -281,30 +289,44 @@ declare class Fetcher {
|
|
|
281
289
|
declare class Format {
|
|
282
290
|
/**
|
|
283
291
|
* date-fns format() with some shortcuts
|
|
284
|
-
* @param formatStr
|
|
285
|
-
*
|
|
292
|
+
* @param formatStr the format to use
|
|
293
|
+
* @param date the date to format, default `new Date()`
|
|
294
|
+
* @example
|
|
295
|
+
* Format.date('iso') // '2026-04-08T13:56:45Z'
|
|
296
|
+
* Format.date('ymd') // '20260408'
|
|
297
|
+
* Format.date('ymd-hm') // '20260408-1356'
|
|
298
|
+
* Format.date('ymd-hms') // '20260408-135645'
|
|
299
|
+
* Format.date('h:m:s') // '13:56:45'
|
|
300
|
+
* @see more format options https://date-fns.org/v4.1.0/docs/format
|
|
286
301
|
*/
|
|
287
|
-
static date(formatStr?: 'iso' | 'ymd' | string, d?: DateArg<Date>): string;
|
|
302
|
+
static date(formatStr?: 'iso' | 'ymd' | 'ymd-hm' | 'ymd-hms' | 'h:m:s' | string, d?: DateArg<Date>): string;
|
|
288
303
|
/**
|
|
289
304
|
* Round a number to a specific set of places
|
|
290
305
|
*/
|
|
291
306
|
static round(n: number, places?: number): string;
|
|
307
|
+
static plural(amount: number, singular: string, multiple?: string): string;
|
|
292
308
|
/**
|
|
293
309
|
* Make millisecond durations actually readable (eg "123ms", "3.56s", "1m 34s", "3h 24m", "2d 4h")
|
|
310
|
+
* @param ms milliseconds
|
|
311
|
+
* @param style 'digital' to output as 'HH:MM:SS'
|
|
312
|
+
* @see details on 'digital' format https://github.com/ungoldman/format-duration
|
|
313
|
+
* @see waiting on `Intl.DurationFormat({ style: 'digital' })` types https://github.com/microsoft/TypeScript/issues/60608
|
|
294
314
|
*/
|
|
295
|
-
static ms(ms: number): string;
|
|
315
|
+
static ms(ms: number, style?: 'digital'): string;
|
|
296
316
|
static bytes(b: number): string;
|
|
297
317
|
}
|
|
298
318
|
//#endregion
|
|
299
319
|
//#region src/Log.d.ts
|
|
300
320
|
type Severity = 'DEFAULT' | 'DEBUG' | 'INFO' | 'NOTICE' | 'WARNING' | 'ERROR' | 'CRITICAL' | 'ALERT' | 'EMERGENCY';
|
|
301
|
-
type
|
|
321
|
+
type Entry = {
|
|
322
|
+
message?: string;
|
|
302
323
|
severity: Severity;
|
|
303
|
-
|
|
324
|
+
stack?: string;
|
|
325
|
+
details?: unknown[];
|
|
304
326
|
};
|
|
305
327
|
declare class Log {
|
|
306
328
|
#private;
|
|
307
|
-
static
|
|
329
|
+
static getStack(): string[];
|
|
308
330
|
/**
|
|
309
331
|
* Handle first argument being a string or an object with a 'message' prop
|
|
310
332
|
*/
|
|
@@ -316,26 +338,10 @@ declare class Log {
|
|
|
316
338
|
* Logs error details before throwing
|
|
317
339
|
*/
|
|
318
340
|
static error(...input: unknown[]): void;
|
|
319
|
-
static warn(...input: unknown[]):
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
};
|
|
324
|
-
static notice(...input: unknown[]): {
|
|
325
|
-
message: string | undefined;
|
|
326
|
-
details: unknown[];
|
|
327
|
-
options: Options;
|
|
328
|
-
};
|
|
329
|
-
static info(...input: unknown[]): {
|
|
330
|
-
message: string | undefined;
|
|
331
|
-
details: unknown[];
|
|
332
|
-
options: Options;
|
|
333
|
-
};
|
|
334
|
-
static debug(...input: unknown[]): {
|
|
335
|
-
message: string | undefined;
|
|
336
|
-
details: unknown[];
|
|
337
|
-
options: Options;
|
|
338
|
-
} | undefined;
|
|
341
|
+
static warn(...input: unknown[]): Entry;
|
|
342
|
+
static notice(...input: unknown[]): Entry;
|
|
343
|
+
static info(...input: unknown[]): Entry;
|
|
344
|
+
static debug(...input: unknown[]): Entry;
|
|
339
345
|
}
|
|
340
346
|
//#endregion
|
|
341
347
|
//#region src/snapshot.d.ts
|
package/dist/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/File.ts","../src/Dir.ts","../src/Cache.ts","../src/Fetcher.ts","../src/Format.ts","../src/Log.ts","../src/snapshot.ts","../src/timeout.ts","../src/TypeWriter.ts"],"sourcesContent":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/File.ts","../src/Dir.ts","../src/Cache.ts","../src/Fetcher.ts","../src/Format.ts","../src/Log.ts","../src/snapshot.ts","../src/timeout.ts","../src/TypeWriter.ts"],"sourcesContent":[],"mappings":"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"}
|
package/dist/index.mjs
CHANGED
|
@@ -8,6 +8,7 @@ import { parseStream, writeToStream } from "fast-csv";
|
|
|
8
8
|
import { isObjectLike, merge } from "lodash-es";
|
|
9
9
|
import { add, format, formatISO, isAfter } from "date-fns";
|
|
10
10
|
import extractDomain from "extract-domain";
|
|
11
|
+
import formatDuration from "format-duration";
|
|
11
12
|
import { inspect } from "node:util";
|
|
12
13
|
import chalk from "chalk";
|
|
13
14
|
import * as qt from "quicktype-core";
|
|
@@ -168,15 +169,42 @@ var FileType = class {
|
|
|
168
169
|
this.file = new File(filepath);
|
|
169
170
|
if (contents) this.file.write(contents);
|
|
170
171
|
}
|
|
172
|
+
get path() {
|
|
173
|
+
return this.file.path;
|
|
174
|
+
}
|
|
175
|
+
get root() {
|
|
176
|
+
return this.file.root;
|
|
177
|
+
}
|
|
178
|
+
get dir() {
|
|
179
|
+
return this.file.dir;
|
|
180
|
+
}
|
|
181
|
+
get base() {
|
|
182
|
+
return this.file.base;
|
|
183
|
+
}
|
|
184
|
+
get name() {
|
|
185
|
+
return this.file.name;
|
|
186
|
+
}
|
|
187
|
+
get ext() {
|
|
188
|
+
return this.file.ext;
|
|
189
|
+
}
|
|
190
|
+
get type() {
|
|
191
|
+
return this.file.type;
|
|
192
|
+
}
|
|
171
193
|
get exists() {
|
|
172
194
|
return this.file.exists;
|
|
173
195
|
}
|
|
174
|
-
get
|
|
175
|
-
return this.file.
|
|
196
|
+
get stats() {
|
|
197
|
+
return this.file.stats;
|
|
176
198
|
}
|
|
177
199
|
delete() {
|
|
178
200
|
this.file.delete();
|
|
179
201
|
}
|
|
202
|
+
get readStream() {
|
|
203
|
+
return this.file.readStream;
|
|
204
|
+
}
|
|
205
|
+
get writeStream() {
|
|
206
|
+
return this.file.writeStream;
|
|
207
|
+
}
|
|
180
208
|
};
|
|
181
209
|
/**
|
|
182
210
|
* A .json file that maintains data type when reading/writing.
|
|
@@ -339,9 +367,13 @@ var TempDir = class extends Dir {
|
|
|
339
367
|
}
|
|
340
368
|
};
|
|
341
369
|
/**
|
|
342
|
-
*
|
|
370
|
+
* Current working directory
|
|
343
371
|
*/
|
|
344
|
-
const
|
|
372
|
+
const cwd = new Dir("./");
|
|
373
|
+
/**
|
|
374
|
+
* ./.temp in current working directory
|
|
375
|
+
*/
|
|
376
|
+
const temp = cwd.tempDir(".temp");
|
|
345
377
|
|
|
346
378
|
//#endregion
|
|
347
379
|
//#region src/Cache.ts
|
|
@@ -485,12 +517,22 @@ var Fetcher = class {
|
|
|
485
517
|
var Format = class {
|
|
486
518
|
/**
|
|
487
519
|
* date-fns format() with some shortcuts
|
|
488
|
-
* @param formatStr
|
|
489
|
-
*
|
|
520
|
+
* @param formatStr the format to use
|
|
521
|
+
* @param date the date to format, default `new Date()`
|
|
522
|
+
* @example
|
|
523
|
+
* Format.date('iso') // '2026-04-08T13:56:45Z'
|
|
524
|
+
* Format.date('ymd') // '20260408'
|
|
525
|
+
* Format.date('ymd-hm') // '20260408-1356'
|
|
526
|
+
* Format.date('ymd-hms') // '20260408-135645'
|
|
527
|
+
* Format.date('h:m:s') // '13:56:45'
|
|
528
|
+
* @see more format options https://date-fns.org/v4.1.0/docs/format
|
|
490
529
|
*/
|
|
491
530
|
static date(formatStr = "iso", d = /* @__PURE__ */ new Date()) {
|
|
492
531
|
if (formatStr === "iso") return formatISO(d);
|
|
493
|
-
if (formatStr === "ymd") return format(d, "
|
|
532
|
+
if (formatStr === "ymd") return format(d, "yyyyMMdd");
|
|
533
|
+
if (formatStr === "ymd-hm") return format(d, "yyyyMMdd-HHmm");
|
|
534
|
+
if (formatStr === "ymd-hms") return format(d, "yyyyMMdd-HHmmss");
|
|
535
|
+
if (formatStr === "h:m:s") return format(d, "HH:mm:ss");
|
|
494
536
|
return format(d, formatStr);
|
|
495
537
|
}
|
|
496
538
|
/**
|
|
@@ -499,10 +541,18 @@ var Format = class {
|
|
|
499
541
|
static round(n, places = 0) {
|
|
500
542
|
return new Intl.NumberFormat("en-US", { maximumFractionDigits: places }).format(n);
|
|
501
543
|
}
|
|
544
|
+
static plural(amount, singular, multiple) {
|
|
545
|
+
return amount === 1 ? `${amount} ${singular}` : `${amount} ${multiple || singular + "s"}`;
|
|
546
|
+
}
|
|
502
547
|
/**
|
|
503
548
|
* Make millisecond durations actually readable (eg "123ms", "3.56s", "1m 34s", "3h 24m", "2d 4h")
|
|
549
|
+
* @param ms milliseconds
|
|
550
|
+
* @param style 'digital' to output as 'HH:MM:SS'
|
|
551
|
+
* @see details on 'digital' format https://github.com/ungoldman/format-duration
|
|
552
|
+
* @see waiting on `Intl.DurationFormat({ style: 'digital' })` types https://github.com/microsoft/TypeScript/issues/60608
|
|
504
553
|
*/
|
|
505
|
-
static ms(ms) {
|
|
554
|
+
static ms(ms, style) {
|
|
555
|
+
if (style === "digital") return formatDuration(ms, { leading: true });
|
|
506
556
|
if (ms < 1e3) return `${this.round(ms)}ms`;
|
|
507
557
|
const s = ms / 1e3;
|
|
508
558
|
if (s < 60) return `${this.round(s, 2)}s`;
|
|
@@ -531,23 +581,29 @@ var Format = class {
|
|
|
531
581
|
|
|
532
582
|
//#endregion
|
|
533
583
|
//#region src/Log.ts
|
|
534
|
-
var Log = class {
|
|
535
|
-
static
|
|
584
|
+
var Log = class Log {
|
|
585
|
+
static getStack() {
|
|
586
|
+
const details = { stack: "" };
|
|
587
|
+
Error.captureStackTrace(details, Log.getStack);
|
|
588
|
+
return details.stack.split("\n").map((l) => l.trim()).filter((l) => l !== "Error");
|
|
589
|
+
}
|
|
536
590
|
/**
|
|
537
591
|
* Gcloud parses JSON in stdout
|
|
538
592
|
*/
|
|
539
593
|
static #toGcloud(entry) {
|
|
540
|
-
|
|
594
|
+
const details = entry.details?.length === 1 ? entry.details[0] : entry.details;
|
|
595
|
+
const output = {
|
|
541
596
|
...entry,
|
|
542
|
-
details
|
|
543
|
-
|
|
544
|
-
|
|
597
|
+
details,
|
|
598
|
+
stack: entry.stack || this.getStack()
|
|
599
|
+
};
|
|
600
|
+
console.log(JSON.stringify(snapshot(output)));
|
|
545
601
|
}
|
|
546
602
|
/**
|
|
547
603
|
* Includes colors and better inspection for logging during dev
|
|
548
604
|
*/
|
|
549
605
|
static #toConsole(entry, color) {
|
|
550
|
-
if (entry.message) console.log(color(
|
|
606
|
+
if (entry.message) console.log(color(`${Format.date("h:m:s")} [${entry.severity}] ${entry.message}`));
|
|
551
607
|
entry.details?.forEach((detail) => {
|
|
552
608
|
console.log(inspect(detail, {
|
|
553
609
|
depth: 10,
|
|
@@ -557,42 +613,28 @@ var Log = class {
|
|
|
557
613
|
}));
|
|
558
614
|
});
|
|
559
615
|
}
|
|
560
|
-
static #log(
|
|
616
|
+
static #log({ severity, color }, ...input) {
|
|
561
617
|
const { message, details } = this.prepare(...input);
|
|
562
|
-
|
|
563
|
-
this.#toGcloud({
|
|
564
|
-
message,
|
|
565
|
-
severity: options.severity,
|
|
566
|
-
details
|
|
567
|
-
});
|
|
568
|
-
return {
|
|
569
|
-
message,
|
|
570
|
-
details,
|
|
571
|
-
options
|
|
572
|
-
};
|
|
573
|
-
}
|
|
574
|
-
if (!this.isTest) this.#toConsole({
|
|
618
|
+
const entry = {
|
|
575
619
|
message,
|
|
576
|
-
severity
|
|
620
|
+
severity,
|
|
577
621
|
details
|
|
578
|
-
}, options.color);
|
|
579
|
-
return {
|
|
580
|
-
message,
|
|
581
|
-
details,
|
|
582
|
-
options
|
|
583
622
|
};
|
|
623
|
+
if (process.env.K_SERVICE !== void 0 || process.env.CLOUD_RUN_JOB !== void 0) this.#toGcloud(entry);
|
|
624
|
+
else this.#toConsole(entry, color);
|
|
625
|
+
return entry;
|
|
584
626
|
}
|
|
585
627
|
/**
|
|
586
628
|
* Handle first argument being a string or an object with a 'message' prop
|
|
587
629
|
*/
|
|
588
630
|
static prepare(...input) {
|
|
589
|
-
let [
|
|
590
|
-
if (typeof
|
|
591
|
-
message:
|
|
631
|
+
let [firstArg, ...rest] = input;
|
|
632
|
+
if (typeof firstArg === "string") return {
|
|
633
|
+
message: firstArg,
|
|
592
634
|
details: rest
|
|
593
635
|
};
|
|
594
|
-
if (isObjectLike(
|
|
595
|
-
const { message, ...firstDetails } =
|
|
636
|
+
if (isObjectLike(firstArg) && typeof firstArg["message"] === "string") {
|
|
637
|
+
const { message, ...firstDetails } = firstArg;
|
|
596
638
|
return {
|
|
597
639
|
message,
|
|
598
640
|
details: [firstDetails, ...rest]
|
|
@@ -629,7 +671,7 @@ var Log = class {
|
|
|
629
671
|
}, ...input);
|
|
630
672
|
}
|
|
631
673
|
static debug(...input) {
|
|
632
|
-
|
|
674
|
+
return this.#log({
|
|
633
675
|
severity: "DEBUG",
|
|
634
676
|
color: chalk.gray
|
|
635
677
|
}, ...input);
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["output: Record<string, any>","obj: Record<string, any>","parsed: Row[]","#parseVal","#inputPath","#resolved","params: [string, string][]","timeout","#toGcloud","#toConsole","#log"],"sources":["../src/snapshot.ts","../src/File.ts","../src/Dir.ts","../src/Cache.ts","../src/Fetcher.ts","../src/Format.ts","../src/Log.ts","../src/timeout.ts","../src/TypeWriter.ts"],"sourcesContent":["import { isObjectLike } from 'lodash-es';\n\n/**\n * Allows special objects (Error, Headers, Set) to be included in JSON.stringify output\n * functions are removed\n */\nexport function snapshot(i: unknown, max = 50, depth = 0): any {\n if (Array.isArray(i)) {\n if (depth === max) return [];\n return i.map((c) => snapshot(c, max, depth + 1));\n }\n if (typeof i === 'function') return undefined;\n if (!isObjectLike(i)) return i;\n\n if (depth === max) return {};\n let output: Record<string, any> = {};\n // @ts-ignore If it has an 'entries' function, use that for looping (eg. Set, Map, Headers)\n if (typeof i.entries === 'function') {\n // @ts-ignore\n for (let [k, v] of i.entries()) {\n output[k] = snapshot(v, max, depth + 1);\n }\n return output;\n }\n\n // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Enumerability_and_ownership_of_properties\n\n // Get Enumerable, inherited properties\n const obj: Record<string, any> = i!;\n for (let key in obj) {\n output[key] = snapshot(obj[key], max, depth + 1);\n }\n\n // Get Non-enumberable, own properties\n Object.getOwnPropertyNames(obj).forEach((key) => {\n output[key] = snapshot(obj[key], max, depth + 1);\n });\n\n return output;\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport { Readable } from 'node:stream';\nimport { finished } from 'node:stream/promises';\nimport mime from 'mime-types';\nimport { writeToStream, parseStream } from 'fast-csv';\nimport { snapshot } from './snapshot.ts';\n\n/**\n * Represents a file on the file system. If the file doesn't exist, it is created the first time it is written to.\n */\nexport class File {\n path;\n root;\n dir;\n base;\n name;\n ext;\n type;\n\n constructor(filepath: string) {\n this.path = path.resolve(filepath);\n const { root, dir, base, ext, name } = path.parse(this.path);\n this.root = root;\n this.dir = dir;\n this.base = base;\n this.name = name;\n this.ext = ext;\n this.type = mime.lookup(ext) || undefined;\n }\n\n get exists() {\n return fs.existsSync(this.path);\n }\n\n get stats(): Partial<fs.Stats> {\n return this.exists ? fs.statSync(this.path) : {};\n }\n\n /**\n * Deletes the file if it exists\n */\n delete() {\n fs.rmSync(this.path, { force: true });\n }\n\n /**\n * @returns the contents of the file as a string, or undefined if the file doesn't exist\n */\n read() {\n return this.exists ? fs.readFileSync(this.path, 'utf8') : undefined;\n }\n\n /**\n * @returns lines as strings, removes trailing '\\n'\n */\n lines() {\n const contents = (this.read() || '').split('\\n');\n return contents.at(-1)?.length ? contents : contents.slice(0, contents.length - 1);\n }\n\n get readStream() {\n return this.exists ? fs.createReadStream(this.path) : Readable.from([]);\n }\n\n get writeStream() {\n fs.mkdirSync(this.dir, { recursive: true });\n return fs.createWriteStream(this.path);\n }\n\n write(contents: string | ReadableStream) {\n fs.mkdirSync(this.dir, { recursive: true });\n if (typeof contents === 'string') return fs.writeFileSync(this.path, contents);\n if (contents instanceof ReadableStream) return finished(Readable.from(contents).pipe(this.writeStream));\n throw new Error(`Invalid content type: ${typeof contents}`);\n }\n\n /**\n * creates file if it doesn't exist, appends string or array of strings as new lines.\n * File always ends with '\\n', so contents don't need to be read before appending\n */\n append(lines: string | string[]) {\n if (!this.exists) this.write('');\n const contents = Array.isArray(lines) ? lines.join('\\n') : lines;\n fs.appendFileSync(this.path, contents + '\\n');\n }\n\n /**\n * @returns FileTypeJson adaptor for current File, adds '.json' extension if not present.\n * @example\n * const file = new File('./data').json({ key: 'val' }); // FileTypeJson<{ key: string; }>\n * console.log(file.path) // '/path/to/cwd/data.json'\n * file.write({ something: 'else' }) // ❌ property 'something' doesn't exist on type { key: string; }\n * @example\n * const file = new File('./data').json<object>({ key: 'val' }); // FileTypeJson<object>\n * file.write({ something: 'else' }) // ✅ data is typed as object\n */\n json<T>(contents?: T) {\n return new FileTypeJson<T>(this.path, contents);\n }\n\n /**\n * @example\n * const file = new File.json('data.json', { key: 'val' }); // FileTypeJson<{ key: string; }>\n */\n static get json() {\n return FileTypeJson;\n }\n\n /**\n * @returns FileTypeNdjson adaptor for current File, adds '.ndjson' extension if not present.\n */\n ndjson<T extends object>(lines?: T | T[]) {\n return new FileTypeNdjson<T>(this.path, lines);\n }\n /**\n * @example\n * const file = new File.ndjson('log', { key: 'val' }); // FileTypeNdjson<{ key: string; }>\n * console.log(file.path) // /path/to/cwd/log.ndjson\n */\n static get ndjson() {\n return FileTypeNdjson;\n }\n\n /**\n * @returns FileTypeCsv adaptor for current File, adds '.csv' extension if not present.\n * @example\n * const file = await new File('a').csv([{ col: 'val' }, { col: 'val2' }]); // FileTypeCsv<{ col: string; }>\n * await file.write([ { col2: 'val2' } ]); // ❌ 'col2' doesn't exist on type { col: string; }\n * await file.write({ col: 'val' }); // ✅ Writes one row\n * await file.write([{ col: 'val2' }, { col: 'val3' }]); // ✅ Writes multiple rows\n */\n async csv<T extends object>(rows?: T[], keys?: (keyof T)[]) {\n const csvFile = new FileTypeCsv<T>(this.path);\n if (rows) await csvFile.write(rows, keys);\n return csvFile;\n }\n\n static get csv() {\n return FileTypeCsv;\n }\n}\n\n/**\n * A generic file adaptor, extended by specific file type implementations\n */\nexport class FileType {\n file;\n\n constructor(filepath: string, contents?: string) {\n this.file = new File(filepath);\n if (contents) this.file.write(contents);\n }\n\n get exists() {\n return this.file.exists;\n }\n\n get path() {\n return this.file.path;\n }\n\n delete() {\n this.file.delete();\n }\n}\n\n/**\n * A .json file that maintains data type when reading/writing.\n * > ⚠️ This is mildly unsafe, important/foreign json files should be validated at runtime!\n * @example\n * const file = new FileTypeJson('./data', { key: 'val' }); // FileTypeJson<{ key: string; }>\n * console.log(file.path) // '/path/to/cwd/data.json'\n * file.write({ something: 'else' }) // ❌ property 'something' doesn't exist on type { key: string; }\n * @example\n * const file = new FileTypeJson<object>('./data', { key: 'val' }); // FileTypeJson<object>\n * file.write({ something: 'else' }) // ✅ data is typed as object\n */\nexport class FileTypeJson<T> extends FileType {\n constructor(filepath: string, contents?: T) {\n super(filepath.endsWith('.json') ? filepath : filepath + '.json');\n if (contents) this.write(contents);\n }\n\n read() {\n const contents = this.file.read();\n return contents ? (JSON.parse(contents) as T) : undefined;\n }\n\n write(contents: T) {\n this.file.write(JSON.stringify(snapshot(contents), null, 2));\n }\n}\n\n/**\n * New-line delimited json file (.ndjson)\n * @see https://jsonltools.com/ndjson-format-specification\n */\nexport class FileTypeNdjson<T extends object> extends FileType {\n constructor(filepath: string, lines?: T | T[]) {\n super(filepath.endsWith('.ndjson') ? filepath : filepath + '.ndjson');\n if (lines) this.append(lines);\n }\n\n append(lines: T | T[]) {\n this.file.append(\n Array.isArray(lines) ? lines.map((l) => JSON.stringify(snapshot(l))) : JSON.stringify(snapshot(lines)),\n );\n }\n\n lines() {\n return this.file.lines().map((l) => JSON.parse(l) as T);\n }\n}\n\ntype Key<T extends object> = keyof T;\n\n/**\n * Comma separated values (.csv).\n * Input rows as objects, keys are used as column headers\n */\nexport class FileTypeCsv<Row extends object> extends FileType {\n constructor(filepath: string) {\n super(filepath.endsWith('.csv') ? filepath : filepath + '.csv');\n }\n\n async write(rows: Row[], keys?: Key<Row>[]) {\n const headerSet = new Set<Key<Row>>();\n if (keys) {\n for (const key of keys) headerSet.add(key);\n } else {\n for (const row of rows) {\n for (const key in row) headerSet.add(key);\n }\n }\n const headers = Array.from(headerSet);\n const outRows = rows.map((row) => headers.map((key) => row[key]));\n return finished(writeToStream(this.file.writeStream, [headers, ...outRows]));\n }\n\n #parseVal(val: string) {\n if (val.toLowerCase() === 'false') return false;\n if (val.toLowerCase() === 'true') return true;\n if (val.length === 0) return null;\n if (/^[\\.0-9]+$/.test(val)) return Number(val);\n return val;\n }\n\n async read() {\n return new Promise<Row[]>((resolve, reject) => {\n const parsed: Row[] = [];\n parseStream(this.file.readStream, { headers: true })\n .on('data', (raw: Record<Key<Row>, string>) => {\n parsed.push(\n Object.entries(raw).reduce(\n (all, [key, val]) => ({\n ...all,\n [key]: this.#parseVal(val as string),\n }),\n {} as Row,\n ),\n );\n })\n .on('error', (e) => reject(e))\n .on('end', () => resolve(parsed));\n });\n }\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport sanitizeFilename from 'sanitize-filename';\nimport { File } from './File.ts';\n\n/**\n * Reference to a specific directory with methods to create and list files.\n * Default path: '.'\n * > Created on file system the first time .path is read or any methods are used\n */\nexport class Dir {\n #inputPath;\n #resolved?: string;\n\n /**\n * @param path can be relative to workspace or absolute\n */\n constructor(inputPath = '.') {\n this.#inputPath = inputPath;\n }\n\n /**\n * The path of this Dir instance. Created on file system the first time this property is read/used.\n */\n get path() {\n if (!this.#resolved) {\n this.#resolved = path.resolve(this.#inputPath);\n fs.mkdirSync(this.#resolved, { recursive: true });\n }\n return this.#resolved;\n }\n\n /**\n * Create a new Dir inside the current Dir\n * @param subPath joined with parent Dir's path to make new Dir\n * @example\n * const folder = new Dir('example');\n * // folder.path = '/path/to/cwd/example'\n * const child = folder.dir('path/to/dir');\n * // child.path = '/path/to/cwd/example/path/to/dir'\n */\n dir(subPath: string) {\n return new Dir(path.join(this.path, subPath));\n }\n\n /**\n * Creates a new TempDir inside current Dir\n * @param subPath joined with parent Dir's path to make new TempDir\n */\n tempDir(subPath: string) {\n return new TempDir(path.join(this.path, subPath));\n }\n\n sanitize(filename: string) {\n const notUrl = filename.replace('https://', '').replace('www.', '');\n return sanitizeFilename(notUrl, { replacement: '_' }).slice(-200);\n }\n\n /**\n * @param base - The file base (name and extension)\n * @example\n * const folder = new Dir('example');\n * const filepath = folder.resolve('file.json');\n * // 'example/file.json'\n */\n filepath(base: string) {\n return path.resolve(this.path, this.sanitize(base));\n }\n\n file(base: string) {\n return new File(this.filepath(base));\n }\n\n get files() {\n return fs.readdirSync(this.path).map((filename) => this.file(filename));\n }\n}\n\n/**\n * Extends Dir class with method to `clear()` contents.\n * Default path: `./.temp`\n */\nexport class TempDir extends Dir {\n constructor(inputPath = `./.temp`) {\n super(inputPath);\n }\n\n /**\n * > ⚠️ Warning! This deletes the directory!\n */\n clear() {\n fs.rmSync(this.path, { recursive: true, force: true });\n fs.mkdirSync(this.path, { recursive: true });\n }\n}\n\n/**\n * './.temp' in current working directory\n */\nexport const temp = new TempDir();\n","import { type Duration, isAfter, add } from 'date-fns';\nimport { TempDir } from './Dir.ts';\n\n/**\n * Save data to a local file with an expiration.\n * Fresh/stale data is returned with a flag for if it's fresh or not,\n * so stale data can still be used if needed.\n */\nexport class Cache<T> {\n file;\n ttl;\n\n constructor(key: string, ttl: number | Duration, initialData?: T) {\n const dir = new TempDir('.cache');\n this.file = dir.file(key).json<{ savedAt: string; data: T }>();\n this.ttl = typeof ttl === 'number' ? { minutes: ttl } : ttl;\n if (initialData) this.write(initialData);\n }\n\n write(data: T) {\n this.file.write({ savedAt: new Date().toUTCString(), data });\n }\n\n read(): [T | undefined, boolean] {\n const { savedAt, data } = this.file.read() || {};\n const isFresh = Boolean(savedAt && isAfter(add(savedAt, this.ttl), new Date()));\n return [data, isFresh];\n }\n}\n","import { merge } from 'lodash-es';\nimport extractDomain from 'extract-domain';\n\nexport type Route = string | URL;\n\ntype QueryVal = string | number | boolean | null | undefined;\nexport type Query = Record<string, QueryVal | QueryVal[]>;\n\nexport type FetchOptions = RequestInit & {\n base?: string;\n query?: Query;\n headers?: Record<string, string>;\n data?: any;\n timeout?: number;\n retries?: number;\n retryDelay?: number;\n};\n\n/**\n * Fetcher provides a quick way to set up a basic API connection\n * with options applied to every request.\n * Includes basic methods for requesting and parsing responses\n */\nexport class Fetcher {\n defaultOptions;\n\n constructor(opts: FetchOptions = {}) {\n this.defaultOptions = {\n timeout: 60000,\n retries: 0,\n retryDelay: 3000,\n ...opts,\n };\n }\n\n /**\n * Build URL with URLSearchParams if query is provided.\n * Also returns domain, to help with cookies\n */\n buildUrl(route: Route, opts: FetchOptions = {}): [URL, string] {\n const mergedOptions = merge({}, this.defaultOptions, opts);\n const params: [string, string][] = [];\n Object.entries(mergedOptions.query || {}).forEach(([key, val]) => {\n if (val === undefined) return;\n if (Array.isArray(val)) {\n val.forEach((v) => {\n params.push([key, `${v}`]);\n });\n } else {\n params.push([key, `${val}`]);\n }\n });\n const search = params.length > 0 ? '?' + new URLSearchParams(params).toString() : '';\n const url = new URL(route + search, this.defaultOptions.base);\n const domain = extractDomain(url.href) as string;\n return [url, domain];\n }\n\n /**\n * Merges options to get headers. Useful when extending the Fetcher class to add custom auth.\n */\n buildHeaders(route: Route, opts: FetchOptions = {}) {\n const { headers } = merge({}, this.defaultOptions, opts);\n return headers || {};\n }\n\n /**\n * Builds request, merging defaultOptions and provided options.\n * Includes Abort signal for timeout\n */\n buildRequest(route: Route, opts: FetchOptions = {}): [Request, FetchOptions, string] {\n const mergedOptions = merge({}, this.defaultOptions, opts);\n const { query, data, timeout, retries, ...init } = mergedOptions;\n init.headers = this.buildHeaders(route, mergedOptions);\n if (data) {\n init.headers['content-type'] = init.headers['content-type'] || 'application/json';\n init.method = init.method || 'POST';\n init.body = JSON.stringify(data);\n }\n if (timeout) {\n init.signal = AbortSignal.timeout(timeout);\n }\n const [url, domain] = this.buildUrl(route, mergedOptions);\n const req = new Request(url, init);\n return [req, mergedOptions, domain];\n }\n\n /**\n * Builds and performs the request, merging provided options with defaultOptions.\n * If `opts.data` is provided, method is updated to POST, content-type json, data is stringified in the body.\n * Retries on local or network error, with increasing backoff.\n */\n async fetch(route: Route, opts: FetchOptions = {}): Promise<[Response, Request]> {\n const [_req, options] = this.buildRequest(route, opts);\n const maxAttempts = (options.retries || 0) + 1;\n let attempt = 0;\n while (attempt < maxAttempts) {\n attempt++;\n const [req] = this.buildRequest(route, opts);\n const res = await fetch(req)\n .then((r) => {\n if (!r.ok) throw new Error(r.statusText);\n return r;\n })\n .catch(async (error) => {\n if (attempt < maxAttempts) {\n const wait = attempt * 3000;\n console.warn(`${req.method} ${req.url} (attempt ${attempt} of ${maxAttempts})`, error);\n await new Promise((resolve) => setTimeout(resolve, wait));\n } else {\n throw new Error(error);\n }\n });\n if (res) return [res, req];\n }\n throw new Error(`Failed to fetch ${_req.url}`);\n }\n\n async fetchText(route: Route, opts: FetchOptions = {}): Promise<[string, Response, Request]> {\n return this.fetch(route, opts).then(async ([res, req]) => {\n const text = await res.text();\n return [text, res, req];\n });\n }\n\n async fetchJson<T>(route: Route, opts: FetchOptions = {}): Promise<[T, Response, Request]> {\n return this.fetchText(route, opts).then(([txt, res, req]) => [JSON.parse(txt) as T, res, req]);\n }\n}\n","import { format, formatISO, type DateArg } from 'date-fns';\n\n/**\n * Helpers for formatting dates, times, and numbers as strings\n */\nexport class Format {\n /**\n * date-fns format() with some shortcuts\n * @param formatStr\n * 'iso' to get ISO date, 'ymd' to format as 'yyyy-MM-dd', full options: https://date-fns.org/v4.1.0/docs/format\n */\n static date(formatStr: 'iso' | 'ymd' | string = 'iso', d: DateArg<Date> = new Date()) {\n if (formatStr === 'iso') return formatISO(d);\n if (formatStr === 'ymd') return format(d, 'yyyy-MM-dd');\n return format(d, formatStr);\n }\n\n /**\n * Round a number to a specific set of places\n */\n static round(n: number, places = 0) {\n return new Intl.NumberFormat('en-US', { maximumFractionDigits: places }).format(n);\n }\n\n /**\n * Make millisecond durations actually readable (eg \"123ms\", \"3.56s\", \"1m 34s\", \"3h 24m\", \"2d 4h\")\n */\n static ms(ms: number) {\n if (ms < 1000) return `${this.round(ms)}ms`;\n const s = ms / 1000;\n if (s < 60) return `${this.round(s, 2)}s`;\n const m = Math.floor(s / 60);\n if (m < 60) return `${m}m ${Math.floor(s) % 60}s`;\n const h = Math.floor(m / 60);\n if (h < 24) return `${h}h ${m % 60}m`;\n const d = Math.floor(h / 24);\n return `${d}d ${h % 24}h`;\n }\n\n static bytes(b: number) {\n const labels = ['b', 'KB', 'MB', 'GB', 'TB'];\n let factor = 0;\n while (b >= 1024 && labels[factor + 1]) {\n b = b / 1024;\n factor++;\n }\n return `${this.round(b, 2)} ${labels[factor]}`;\n }\n}\n","import { inspect } from 'node:util';\nimport { isObjectLike } from 'lodash-es';\nimport chalk, { type ChalkInstance } from 'chalk';\nimport { snapshot } from './snapshot.ts';\n\ntype Severity = 'DEFAULT' | 'DEBUG' | 'INFO' | 'NOTICE' | 'WARNING' | 'ERROR' | 'CRITICAL' | 'ALERT' | 'EMERGENCY';\n\ntype Options = {\n severity: Severity;\n color: ChalkInstance;\n};\n\ntype Entry = {\n message?: string;\n severity: Severity;\n details?: unknown[];\n};\n\nexport class Log {\n // Only silence logs when THIS package is running its own tests\n static isTest = process.env.npm_package_name === '@brianbuie/node-kit' && process.env.npm_lifecycle_event === 'test';\n\n /**\n * Gcloud parses JSON in stdout\n */\n static #toGcloud(entry: Entry) {\n if (entry.details?.length === 1) {\n console.log(JSON.stringify(snapshot({ ...entry, details: entry.details[0] })));\n } else {\n console.log(JSON.stringify(snapshot(entry)));\n }\n }\n\n /**\n * Includes colors and better inspection for logging during dev\n */\n static #toConsole(entry: Entry, color: ChalkInstance) {\n if (entry.message) console.log(color(`[${entry.severity}] ${entry.message}`));\n entry.details?.forEach((detail) => {\n console.log(inspect(detail, { depth: 10, breakLength: 100, compact: true, colors: true }));\n });\n }\n\n static #log(options: Options, ...input: unknown[]) {\n const { message, details } = this.prepare(...input);\n // https://cloud.google.com/run/docs/container-contract#env-vars\n const isGcloud = process.env.K_SERVICE !== undefined || process.env.CLOUD_RUN_JOB !== undefined;\n if (isGcloud) {\n this.#toGcloud({ message, severity: options.severity, details });\n return { message, details, options };\n }\n // Hide output while testing this package\n if (!this.isTest) {\n this.#toConsole({ message, severity: options.severity, details }, options.color);\n }\n return { message, details, options };\n }\n\n /**\n * Handle first argument being a string or an object with a 'message' prop\n */\n static prepare(...input: unknown[]): { message?: string; details: unknown[] } {\n let [first, ...rest] = input;\n if (typeof first === 'string') {\n return { message: first, details: rest };\n }\n // @ts-ignore\n if (isObjectLike(first) && typeof first['message'] === 'string') {\n const { message, ...firstDetails } = first as { message: string };\n return { message, details: [firstDetails, ...rest] };\n }\n return { details: input };\n }\n\n /**\n * Logs error details before throwing\n */\n static error(...input: unknown[]) {\n const { message } = this.#log({ severity: 'ERROR', color: chalk.red }, ...input);\n throw new Error(message);\n }\n\n static warn(...input: unknown[]) {\n return this.#log({ severity: 'WARNING', color: chalk.yellow }, ...input);\n }\n\n static notice(...input: unknown[]) {\n return this.#log({ severity: 'NOTICE', color: chalk.cyan }, ...input);\n }\n\n static info(...input: unknown[]) {\n return this.#log({ severity: 'INFO', color: chalk.white }, ...input);\n }\n\n static debug(...input: unknown[]) {\n const debugging = process.argv.some((arg) => arg.includes('--debug')) || process.env.DEBUG !== undefined;\n if (debugging || process.env.NODE_ENV !== 'production') {\n return this.#log({ severity: 'DEBUG', color: chalk.gray }, ...input);\n }\n }\n}\n","export async function timeout(ms: number) {\n return new Promise((resolve) => {\n setTimeout(resolve, ms);\n });\n}\n","import * as fs from 'node:fs';\nimport { merge } from 'lodash-es';\nimport * as qt from 'quicktype-core';\n\nexport class TypeWriter {\n moduleName;\n input = qt.jsonInputForTargetLanguage('typescript');\n outDir;\n qtSettings;\n\n constructor(moduleName: string, settings: { outDir?: string } & Partial<qt.Options> = {}) {\n this.moduleName = moduleName;\n const { outDir, ...qtSettings } = settings;\n this.outDir = outDir || './types';\n const defaultSettings = {\n lang: 'typescript',\n rendererOptions: {\n 'just-types': true,\n 'prefer-types': true,\n },\n inferEnums: false,\n inferDateTimes: false,\n };\n this.qtSettings = merge(defaultSettings, qtSettings);\n }\n\n async addMember(name: string, _samples: any[]) {\n const samples = _samples.map((s) => (typeof s === 'string' ? s : JSON.stringify(s)));\n await this.input.addSource({ name, samples });\n }\n\n async toString() {\n const inputData = new qt.InputData();\n inputData.addInput(this.input);\n const result = await qt.quicktype({\n inputData,\n ...this.qtSettings,\n });\n return result.lines.join('\\n');\n }\n\n async toFile() {\n const result = await this.toString();\n fs.mkdirSync(this.outDir, { recursive: true });\n fs.writeFileSync(`${this.outDir}/${this.moduleName}.d.ts`, result);\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["output: Record<string, any>","obj: Record<string, any>","parsed: Row[]","#parseVal","#inputPath","#resolved","params: [string, string][]","timeout","#toGcloud","#toConsole","#log","entry: Entry"],"sources":["../src/snapshot.ts","../src/File.ts","../src/Dir.ts","../src/Cache.ts","../src/Fetcher.ts","../src/Format.ts","../src/Log.ts","../src/timeout.ts","../src/TypeWriter.ts"],"sourcesContent":["import { isObjectLike } from 'lodash-es';\n\n/**\n * Allows special objects (Error, Headers, Set) to be included in JSON.stringify output\n * functions are removed\n */\nexport function snapshot(i: unknown, max = 50, depth = 0): any {\n if (Array.isArray(i)) {\n if (depth === max) return [];\n return i.map((c) => snapshot(c, max, depth + 1));\n }\n if (typeof i === 'function') return undefined;\n if (!isObjectLike(i)) return i;\n\n if (depth === max) return {};\n let output: Record<string, any> = {};\n // @ts-ignore If it has an 'entries' function, use that for looping (eg. Set, Map, Headers)\n if (typeof i.entries === 'function') {\n // @ts-ignore\n for (let [k, v] of i.entries()) {\n output[k] = snapshot(v, max, depth + 1);\n }\n return output;\n }\n\n // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Enumerability_and_ownership_of_properties\n\n // Get Enumerable, inherited properties\n const obj: Record<string, any> = i!;\n for (let key in obj) {\n output[key] = snapshot(obj[key], max, depth + 1);\n }\n\n // Get Non-enumberable, own properties\n Object.getOwnPropertyNames(obj).forEach((key) => {\n output[key] = snapshot(obj[key], max, depth + 1);\n });\n\n return output;\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport { Readable } from 'node:stream';\nimport { finished } from 'node:stream/promises';\nimport mime from 'mime-types';\nimport { writeToStream, parseStream } from 'fast-csv';\nimport { snapshot } from './snapshot.ts';\n\n/**\n * Represents a file on the file system. If the file doesn't exist, it is created the first time it is written to.\n */\nexport class File {\n path;\n root;\n dir;\n base;\n name;\n ext;\n type;\n\n constructor(filepath: string) {\n this.path = path.resolve(filepath);\n const { root, dir, base, ext, name } = path.parse(this.path);\n this.root = root;\n this.dir = dir;\n this.base = base;\n this.name = name;\n this.ext = ext;\n this.type = mime.lookup(ext) || undefined;\n }\n\n get exists() {\n return fs.existsSync(this.path);\n }\n\n get stats(): Partial<fs.Stats> {\n return this.exists ? fs.statSync(this.path) : {};\n }\n\n /**\n * Deletes the file if it exists\n */\n delete() {\n fs.rmSync(this.path, { force: true });\n }\n\n /**\n * @returns the contents of the file as a string, or undefined if the file doesn't exist\n */\n read() {\n return this.exists ? fs.readFileSync(this.path, 'utf8') : undefined;\n }\n\n /**\n * @returns lines as strings, removes trailing '\\n'\n */\n lines() {\n const contents = (this.read() || '').split('\\n');\n return contents.at(-1)?.length ? contents : contents.slice(0, contents.length - 1);\n }\n\n get readStream() {\n return this.exists ? fs.createReadStream(this.path) : Readable.from([]);\n }\n\n get writeStream() {\n fs.mkdirSync(this.dir, { recursive: true });\n return fs.createWriteStream(this.path);\n }\n\n write(contents: string | ReadableStream) {\n fs.mkdirSync(this.dir, { recursive: true });\n if (typeof contents === 'string') return fs.writeFileSync(this.path, contents);\n if (contents instanceof ReadableStream) return finished(Readable.from(contents).pipe(this.writeStream));\n throw new Error(`Invalid content type: ${typeof contents}`);\n }\n\n /**\n * creates file if it doesn't exist, appends string or array of strings as new lines.\n * File always ends with '\\n', so contents don't need to be read before appending\n */\n append(lines: string | string[]) {\n if (!this.exists) this.write('');\n const contents = Array.isArray(lines) ? lines.join('\\n') : lines;\n fs.appendFileSync(this.path, contents + '\\n');\n }\n\n /**\n * @returns FileTypeJson adaptor for current File, adds '.json' extension if not present.\n * @example\n * const file = new File('./data').json({ key: 'val' }); // FileTypeJson<{ key: string; }>\n * console.log(file.path) // '/path/to/cwd/data.json'\n * file.write({ something: 'else' }) // ❌ property 'something' doesn't exist on type { key: string; }\n * @example\n * const file = new File('./data').json<object>({ key: 'val' }); // FileTypeJson<object>\n * file.write({ something: 'else' }) // ✅ data is typed as object\n */\n json<T>(contents?: T) {\n return new FileTypeJson<T>(this.path, contents);\n }\n\n /**\n * @example\n * const file = new File.json('data.json', { key: 'val' }); // FileTypeJson<{ key: string; }>\n */\n static get json() {\n return FileTypeJson;\n }\n\n /**\n * @returns FileTypeNdjson adaptor for current File, adds '.ndjson' extension if not present.\n */\n ndjson<T extends object>(lines?: T | T[]) {\n return new FileTypeNdjson<T>(this.path, lines);\n }\n /**\n * @example\n * const file = new File.ndjson('log', { key: 'val' }); // FileTypeNdjson<{ key: string; }>\n * console.log(file.path) // /path/to/cwd/log.ndjson\n */\n static get ndjson() {\n return FileTypeNdjson;\n }\n\n /**\n * @returns FileTypeCsv adaptor for current File, adds '.csv' extension if not present.\n * @example\n * const file = await new File('a').csv([{ col: 'val' }, { col: 'val2' }]); // FileTypeCsv<{ col: string; }>\n * await file.write([ { col2: 'val2' } ]); // ❌ 'col2' doesn't exist on type { col: string; }\n * await file.write({ col: 'val' }); // ✅ Writes one row\n * await file.write([{ col: 'val2' }, { col: 'val3' }]); // ✅ Writes multiple rows\n */\n async csv<T extends object>(rows?: T[], keys?: (keyof T)[]) {\n const csvFile = new FileTypeCsv<T>(this.path);\n if (rows) await csvFile.write(rows, keys);\n return csvFile;\n }\n\n static get csv() {\n return FileTypeCsv;\n }\n}\n\n/**\n * A generic file adaptor, extended by specific file type implementations\n */\nexport class FileType {\n file;\n\n constructor(filepath: string, contents?: string) {\n this.file = new File(filepath);\n if (contents) this.file.write(contents);\n }\n\n get path() {\n return this.file.path;\n }\n\n get root() {\n return this.file.root;\n }\n\n get dir() {\n return this.file.dir;\n }\n\n get base() {\n return this.file.base;\n }\n\n get name() {\n return this.file.name;\n }\n\n get ext() {\n return this.file.ext;\n }\n\n get type() {\n return this.file.type;\n }\n\n get exists() {\n return this.file.exists;\n }\n\n get stats() {\n return this.file.stats;\n }\n\n delete() {\n this.file.delete();\n }\n\n get readStream() {\n return this.file.readStream;\n }\n\n get writeStream() {\n return this.file.writeStream;\n }\n}\n\n/**\n * A .json file that maintains data type when reading/writing.\n * > ⚠️ This is mildly unsafe, important/foreign json files should be validated at runtime!\n * @example\n * const file = new FileTypeJson('./data', { key: 'val' }); // FileTypeJson<{ key: string; }>\n * console.log(file.path) // '/path/to/cwd/data.json'\n * file.write({ something: 'else' }) // ❌ property 'something' doesn't exist on type { key: string; }\n * @example\n * const file = new FileTypeJson<object>('./data', { key: 'val' }); // FileTypeJson<object>\n * file.write({ something: 'else' }) // ✅ data is typed as object\n */\nexport class FileTypeJson<T> extends FileType {\n constructor(filepath: string, contents?: T) {\n super(filepath.endsWith('.json') ? filepath : filepath + '.json');\n if (contents) this.write(contents);\n }\n\n read() {\n const contents = this.file.read();\n return contents ? (JSON.parse(contents) as T) : undefined;\n }\n\n write(contents: T) {\n this.file.write(JSON.stringify(snapshot(contents), null, 2));\n }\n}\n\n/**\n * New-line delimited json file (.ndjson)\n * @see https://jsonltools.com/ndjson-format-specification\n */\nexport class FileTypeNdjson<T extends object> extends FileType {\n constructor(filepath: string, lines?: T | T[]) {\n super(filepath.endsWith('.ndjson') ? filepath : filepath + '.ndjson');\n if (lines) this.append(lines);\n }\n\n append(lines: T | T[]) {\n this.file.append(\n Array.isArray(lines) ? lines.map(l => JSON.stringify(snapshot(l))) : JSON.stringify(snapshot(lines)),\n );\n }\n\n lines() {\n return this.file.lines().map(l => JSON.parse(l) as T);\n }\n}\n\ntype Key<T extends object> = keyof T;\n\n/**\n * Comma separated values (.csv).\n * Input rows as objects, keys are used as column headers\n */\nexport class FileTypeCsv<Row extends object> extends FileType {\n constructor(filepath: string) {\n super(filepath.endsWith('.csv') ? filepath : filepath + '.csv');\n }\n\n async write(rows: Row[], keys?: Key<Row>[]) {\n const headerSet = new Set<Key<Row>>();\n if (keys) {\n for (const key of keys) headerSet.add(key);\n } else {\n for (const row of rows) {\n for (const key in row) headerSet.add(key);\n }\n }\n const headers = Array.from(headerSet);\n const outRows = rows.map(row => headers.map(key => row[key]));\n return finished(writeToStream(this.file.writeStream, [headers, ...outRows]));\n }\n\n #parseVal(val: string) {\n if (val.toLowerCase() === 'false') return false;\n if (val.toLowerCase() === 'true') return true;\n if (val.length === 0) return null;\n if (/^[\\.0-9]+$/.test(val)) return Number(val);\n return val;\n }\n\n async read() {\n return new Promise<Row[]>((resolve, reject) => {\n const parsed: Row[] = [];\n parseStream(this.file.readStream, { headers: true })\n .on('data', (raw: Record<Key<Row>, string>) => {\n parsed.push(\n Object.entries(raw).reduce(\n (all, [key, val]) => ({\n ...all,\n [key]: this.#parseVal(val as string),\n }),\n {} as Row,\n ),\n );\n })\n .on('error', e => reject(e))\n .on('end', () => resolve(parsed));\n });\n }\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport sanitizeFilename from 'sanitize-filename';\nimport { File } from './File.ts';\n\n/**\n * Reference to a specific directory with methods to create and list files.\n * Default path: '.'\n * > Created on file system the first time .path is read or any methods are used\n */\nexport class Dir {\n #inputPath;\n #resolved?: string;\n\n /**\n * @param path can be relative to workspace or absolute\n */\n constructor(inputPath = '.') {\n this.#inputPath = inputPath;\n }\n\n /**\n * The path of this Dir instance. Created on file system the first time this property is read/used.\n */\n get path() {\n if (!this.#resolved) {\n this.#resolved = path.resolve(this.#inputPath);\n fs.mkdirSync(this.#resolved, { recursive: true });\n }\n return this.#resolved;\n }\n\n /**\n * Create a new Dir inside the current Dir\n * @param subPath joined with parent Dir's path to make new Dir\n * @example\n * const folder = new Dir('example');\n * // folder.path = '/path/to/cwd/example'\n * const child = folder.dir('path/to/dir');\n * // child.path = '/path/to/cwd/example/path/to/dir'\n */\n dir(subPath: string) {\n return new Dir(path.join(this.path, subPath));\n }\n\n /**\n * Creates a new TempDir inside current Dir\n * @param subPath joined with parent Dir's path to make new TempDir\n */\n tempDir(subPath: string) {\n return new TempDir(path.join(this.path, subPath));\n }\n\n sanitize(filename: string) {\n const notUrl = filename.replace('https://', '').replace('www.', '');\n return sanitizeFilename(notUrl, { replacement: '_' }).slice(-200);\n }\n\n /**\n * @param base - The file base (name and extension)\n * @example\n * const folder = new Dir('example');\n * const filepath = folder.resolve('file.json');\n * // 'example/file.json'\n */\n filepath(base: string) {\n return path.resolve(this.path, this.sanitize(base));\n }\n\n file(base: string) {\n return new File(this.filepath(base));\n }\n\n get files() {\n return fs.readdirSync(this.path).map(filename => this.file(filename));\n }\n}\n\n/**\n * Extends Dir class with method to `clear()` contents.\n * Default path: `./.temp`\n */\nexport class TempDir extends Dir {\n constructor(inputPath = `./.temp`) {\n super(inputPath);\n }\n\n /**\n * > ⚠️ Warning! This deletes the directory!\n */\n clear() {\n fs.rmSync(this.path, { recursive: true, force: true });\n fs.mkdirSync(this.path, { recursive: true });\n }\n}\n\n/**\n * Current working directory\n */\nexport const cwd = new Dir('./');\n/**\n * ./.temp in current working directory\n */\nexport const temp = cwd.tempDir('.temp');\n","import { type Duration, isAfter, add } from 'date-fns';\nimport { TempDir } from './Dir.ts';\n\n/**\n * Save data to a local file with an expiration.\n * Fresh/stale data is returned with a flag for if it's fresh or not,\n * so stale data can still be used if needed.\n */\nexport class Cache<T> {\n file;\n ttl;\n\n constructor(key: string, ttl: number | Duration, initialData?: T) {\n const dir = new TempDir('.cache');\n this.file = dir.file(key).json<{ savedAt: string; data: T }>();\n this.ttl = typeof ttl === 'number' ? { minutes: ttl } : ttl;\n if (initialData) this.write(initialData);\n }\n\n write(data: T) {\n this.file.write({ savedAt: new Date().toUTCString(), data });\n }\n\n read(): [T | undefined, boolean] {\n const { savedAt, data } = this.file.read() || {};\n const isFresh = Boolean(savedAt && isAfter(add(savedAt, this.ttl), new Date()));\n return [data, isFresh];\n }\n}\n","import { merge } from 'lodash-es';\nimport extractDomain from 'extract-domain';\n\nexport type Route = string | URL;\n\ntype QueryVal = string | number | boolean | null | undefined;\nexport type Query = Record<string, QueryVal | QueryVal[]>;\n\nexport type FetchOptions = RequestInit & {\n base?: string;\n query?: Query;\n headers?: Record<string, string>;\n data?: any;\n timeout?: number;\n retries?: number;\n retryDelay?: number;\n};\n\n/**\n * Fetcher provides a quick way to set up a basic API connection\n * with options applied to every request.\n * Includes basic methods for requesting and parsing responses\n */\nexport class Fetcher {\n defaultOptions;\n\n constructor(opts: FetchOptions = {}) {\n this.defaultOptions = {\n timeout: 60000,\n retries: 0,\n retryDelay: 3000,\n ...opts,\n };\n }\n\n /**\n * Build URL with URLSearchParams if query is provided.\n * Also returns domain, to help with cookies\n */\n buildUrl(route: Route, opts: FetchOptions = {}): [URL, string] {\n const mergedOptions = merge({}, this.defaultOptions, opts);\n const params: [string, string][] = [];\n Object.entries(mergedOptions.query || {}).forEach(([key, val]) => {\n if (val === undefined) return;\n if (Array.isArray(val)) {\n val.forEach((v) => {\n params.push([key, `${v}`]);\n });\n } else {\n params.push([key, `${val}`]);\n }\n });\n const search = params.length > 0 ? '?' + new URLSearchParams(params).toString() : '';\n const url = new URL(route + search, this.defaultOptions.base);\n const domain = extractDomain(url.href) as string;\n return [url, domain];\n }\n\n /**\n * Merges options to get headers. Useful when extending the Fetcher class to add custom auth.\n */\n buildHeaders(route: Route, opts: FetchOptions = {}) {\n const { headers } = merge({}, this.defaultOptions, opts);\n return headers || {};\n }\n\n /**\n * Builds request, merging defaultOptions and provided options.\n * Includes Abort signal for timeout\n */\n buildRequest(route: Route, opts: FetchOptions = {}): [Request, FetchOptions, string] {\n const mergedOptions = merge({}, this.defaultOptions, opts);\n const { query, data, timeout, retries, ...init } = mergedOptions;\n init.headers = this.buildHeaders(route, mergedOptions);\n if (data) {\n init.headers['content-type'] = init.headers['content-type'] || 'application/json';\n init.method = init.method || 'POST';\n init.body = JSON.stringify(data);\n }\n if (timeout) {\n init.signal = AbortSignal.timeout(timeout);\n }\n const [url, domain] = this.buildUrl(route, mergedOptions);\n const req = new Request(url, init);\n return [req, mergedOptions, domain];\n }\n\n /**\n * Builds and performs the request, merging provided options with defaultOptions.\n * If `opts.data` is provided, method is updated to POST, content-type json, data is stringified in the body.\n * Retries on local or network error, with increasing backoff.\n */\n async fetch(route: Route, opts: FetchOptions = {}): Promise<[Response, Request]> {\n const [_req, options] = this.buildRequest(route, opts);\n const maxAttempts = (options.retries || 0) + 1;\n let attempt = 0;\n while (attempt < maxAttempts) {\n attempt++;\n const [req] = this.buildRequest(route, opts);\n const res = await fetch(req)\n .then((r) => {\n if (!r.ok) throw new Error(r.statusText);\n return r;\n })\n .catch(async (error) => {\n if (attempt < maxAttempts) {\n const wait = attempt * 3000;\n console.warn(`${req.method} ${req.url} (attempt ${attempt} of ${maxAttempts})`, error);\n await new Promise((resolve) => setTimeout(resolve, wait));\n } else {\n throw new Error(error);\n }\n });\n if (res) return [res, req];\n }\n throw new Error(`Failed to fetch ${_req.url}`);\n }\n\n async fetchText(route: Route, opts: FetchOptions = {}): Promise<[string, Response, Request]> {\n return this.fetch(route, opts).then(async ([res, req]) => {\n const text = await res.text();\n return [text, res, req];\n });\n }\n\n async fetchJson<T>(route: Route, opts: FetchOptions = {}): Promise<[T, Response, Request]> {\n return this.fetchText(route, opts).then(([txt, res, req]) => [JSON.parse(txt) as T, res, req]);\n }\n}\n","import { format, formatISO, type DateArg, type Duration } from 'date-fns';\nimport formatDuration from 'format-duration';\n\n/**\n * Helpers for formatting dates, times, and numbers as strings\n */\nexport class Format {\n /**\n * date-fns format() with some shortcuts\n * @param formatStr the format to use\n * @param date the date to format, default `new Date()`\n * @example\n * Format.date('iso') // '2026-04-08T13:56:45Z'\n * Format.date('ymd') // '20260408'\n * Format.date('ymd-hm') // '20260408-1356'\n * Format.date('ymd-hms') // '20260408-135645'\n * Format.date('h:m:s') // '13:56:45'\n * @see more format options https://date-fns.org/v4.1.0/docs/format\n */\n static date(\n formatStr: 'iso' | 'ymd' | 'ymd-hm' | 'ymd-hms' | 'h:m:s' | string = 'iso',\n d: DateArg<Date> = new Date(),\n ) {\n if (formatStr === 'iso') return formatISO(d);\n if (formatStr === 'ymd') return format(d, 'yyyyMMdd');\n if (formatStr === 'ymd-hm') return format(d, 'yyyyMMdd-HHmm');\n if (formatStr === 'ymd-hms') return format(d, 'yyyyMMdd-HHmmss');\n if (formatStr === 'h:m:s') return format(d, 'HH:mm:ss');\n return format(d, formatStr);\n }\n\n /**\n * Round a number to a specific set of places\n */\n static round(n: number, places = 0) {\n return new Intl.NumberFormat('en-US', { maximumFractionDigits: places }).format(n);\n }\n\n static plural(amount: number, singular: string, multiple?: string) {\n return amount === 1 ? `${amount} ${singular}` : `${amount} ${multiple || singular + 's'}`;\n }\n\n /**\n * Make millisecond durations actually readable (eg \"123ms\", \"3.56s\", \"1m 34s\", \"3h 24m\", \"2d 4h\")\n * @param ms milliseconds\n * @param style 'digital' to output as 'HH:MM:SS'\n * @see details on 'digital' format https://github.com/ungoldman/format-duration\n * @see waiting on `Intl.DurationFormat({ style: 'digital' })` types https://github.com/microsoft/TypeScript/issues/60608\n */\n static ms(ms: number, style?: 'digital') {\n if (style === 'digital') return formatDuration(ms, { leading: true });\n if (ms < 1000) return `${this.round(ms)}ms`;\n const s = ms / 1000;\n if (s < 60) return `${this.round(s, 2)}s`;\n const m = Math.floor(s / 60);\n if (m < 60) return `${m}m ${Math.floor(s) % 60}s`;\n const h = Math.floor(m / 60);\n if (h < 24) return `${h}h ${m % 60}m`;\n const d = Math.floor(h / 24);\n return `${d}d ${h % 24}h`;\n }\n\n static bytes(b: number) {\n const labels = ['b', 'KB', 'MB', 'GB', 'TB'];\n let factor = 0;\n while (b >= 1024 && labels[factor + 1]) {\n b = b / 1024;\n factor++;\n }\n return `${this.round(b, 2)} ${labels[factor]}`;\n }\n}\n","import { inspect } from 'node:util';\nimport { isObjectLike } from 'lodash-es';\nimport chalk, { type ChalkInstance } from 'chalk';\nimport { snapshot } from './snapshot.ts';\nimport { Format } from './Format.ts';\n\ntype Severity = 'DEFAULT' | 'DEBUG' | 'INFO' | 'NOTICE' | 'WARNING' | 'ERROR' | 'CRITICAL' | 'ALERT' | 'EMERGENCY';\n\ntype Options = {\n severity: Severity;\n color: ChalkInstance;\n};\n\ntype Entry = {\n message?: string;\n severity: Severity;\n stack?: string;\n details?: unknown[];\n};\n\nexport class Log {\n static getStack() {\n const details = { stack: '' };\n // replaces details.stack with current stack trace, excluding this Log.getStack call\n Error.captureStackTrace(details, Log.getStack);\n // remove 'Error' on first line\n return details.stack\n .split('\\n')\n .map(l => l.trim())\n .filter(l => l !== 'Error');\n }\n\n /**\n * Gcloud parses JSON in stdout\n */\n static #toGcloud(entry: Entry) {\n const details = entry.details?.length === 1 ? entry.details[0] : entry.details;\n const output = { ...entry, details, stack: entry.stack || this.getStack() };\n console.log(JSON.stringify(snapshot(output)));\n }\n\n /**\n * Includes colors and better inspection for logging during dev\n */\n static #toConsole(entry: Entry, color: ChalkInstance) {\n if (entry.message) console.log(color(`${Format.date('h:m:s')} [${entry.severity}] ${entry.message}`));\n entry.details?.forEach(detail => {\n console.log(inspect(detail, { depth: 10, breakLength: 100, compact: true, colors: true }));\n });\n }\n\n static #log({ severity, color }: Options, ...input: unknown[]) {\n const { message, details } = this.prepare(...input);\n const entry: Entry = { message, severity, details };\n // https://cloud.google.com/run/docs/container-contract#env-vars\n const isGcloud = process.env.K_SERVICE !== undefined || process.env.CLOUD_RUN_JOB !== undefined;\n if (isGcloud) {\n this.#toGcloud(entry);\n } else {\n this.#toConsole(entry, color);\n }\n return entry;\n }\n\n /**\n * Handle first argument being a string or an object with a 'message' prop\n */\n static prepare(...input: unknown[]): { message?: string; details: unknown[] } {\n let [firstArg, ...rest] = input;\n // First argument is a string, use that as the message\n if (typeof firstArg === 'string') {\n return { message: firstArg, details: rest };\n }\n // First argument is an object with a `message` property\n // @ts-ignore\n if (isObjectLike(firstArg) && typeof firstArg['message'] === 'string') {\n const { message, ...firstDetails } = firstArg as { message: string };\n return { message, details: [firstDetails, ...rest] };\n }\n // No message found, log all args as details\n return { details: input };\n }\n\n /**\n * Logs error details before throwing\n */\n static error(...input: unknown[]) {\n const { message } = this.#log({ severity: 'ERROR', color: chalk.red }, ...input);\n throw new Error(message);\n }\n\n static warn(...input: unknown[]) {\n return this.#log({ severity: 'WARNING', color: chalk.yellow }, ...input);\n }\n\n static notice(...input: unknown[]) {\n return this.#log({ severity: 'NOTICE', color: chalk.cyan }, ...input);\n }\n\n static info(...input: unknown[]) {\n return this.#log({ severity: 'INFO', color: chalk.white }, ...input);\n }\n\n static debug(...input: unknown[]) {\n return this.#log({ severity: 'DEBUG', color: chalk.gray }, ...input);\n }\n}\n","export async function timeout(ms: number) {\n return new Promise((resolve) => {\n setTimeout(resolve, ms);\n });\n}\n","import * as fs from 'node:fs';\nimport { merge } from 'lodash-es';\nimport * as qt from 'quicktype-core';\n\nexport class TypeWriter {\n moduleName;\n input = qt.jsonInputForTargetLanguage('typescript');\n outDir;\n qtSettings;\n\n constructor(moduleName: string, settings: { outDir?: string } & Partial<qt.Options> = {}) {\n this.moduleName = moduleName;\n const { outDir, ...qtSettings } = settings;\n this.outDir = outDir || './types';\n const defaultSettings = {\n lang: 'typescript',\n rendererOptions: {\n 'just-types': true,\n 'prefer-types': true,\n },\n inferEnums: false,\n inferDateTimes: false,\n };\n this.qtSettings = merge(defaultSettings, qtSettings);\n }\n\n async addMember(name: string, _samples: any[]) {\n const samples = _samples.map((s) => (typeof s === 'string' ? s : JSON.stringify(s)));\n await this.input.addSource({ name, samples });\n }\n\n async toString() {\n const inputData = new qt.InputData();\n inputData.addInput(this.input);\n const result = await qt.quicktype({\n inputData,\n ...this.qtSettings,\n });\n return result.lines.join('\\n');\n }\n\n async toFile() {\n const result = await this.toString();\n fs.mkdirSync(this.outDir, { recursive: true });\n fs.writeFileSync(`${this.outDir}/${this.moduleName}.d.ts`, result);\n }\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@brianbuie/node-kit",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.5",
|
|
4
4
|
"license": "ISC",
|
|
5
5
|
"description": "Basic tools for Node.js projects",
|
|
6
6
|
"author": "Brian Buie <brian@buie.dev>",
|
|
@@ -38,6 +38,7 @@
|
|
|
38
38
|
"date-fns": "^4.1.0",
|
|
39
39
|
"extract-domain": "^5.0.2",
|
|
40
40
|
"fast-csv": "^5.0.5",
|
|
41
|
+
"format-duration": "^3.0.2",
|
|
41
42
|
"lodash-es": "^4.17.21",
|
|
42
43
|
"mime-types": "^3.0.2",
|
|
43
44
|
"quicktype-core": "^23.2.6",
|
package/prettier.config.ts
CHANGED
package/src/Dir.ts
CHANGED
|
@@ -72,7 +72,7 @@ export class Dir {
|
|
|
72
72
|
}
|
|
73
73
|
|
|
74
74
|
get files() {
|
|
75
|
-
return fs.readdirSync(this.path).map(
|
|
75
|
+
return fs.readdirSync(this.path).map(filename => this.file(filename));
|
|
76
76
|
}
|
|
77
77
|
}
|
|
78
78
|
|
|
@@ -95,6 +95,10 @@ export class TempDir extends Dir {
|
|
|
95
95
|
}
|
|
96
96
|
|
|
97
97
|
/**
|
|
98
|
-
*
|
|
98
|
+
* Current working directory
|
|
99
99
|
*/
|
|
100
|
-
export const
|
|
100
|
+
export const cwd = new Dir('./');
|
|
101
|
+
/**
|
|
102
|
+
* ./.temp in current working directory
|
|
103
|
+
*/
|
|
104
|
+
export const temp = cwd.tempDir('.temp');
|
package/src/File.ts
CHANGED
|
@@ -152,17 +152,53 @@ export class FileType {
|
|
|
152
152
|
if (contents) this.file.write(contents);
|
|
153
153
|
}
|
|
154
154
|
|
|
155
|
+
get path() {
|
|
156
|
+
return this.file.path;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
get root() {
|
|
160
|
+
return this.file.root;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
get dir() {
|
|
164
|
+
return this.file.dir;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
get base() {
|
|
168
|
+
return this.file.base;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
get name() {
|
|
172
|
+
return this.file.name;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
get ext() {
|
|
176
|
+
return this.file.ext;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
get type() {
|
|
180
|
+
return this.file.type;
|
|
181
|
+
}
|
|
182
|
+
|
|
155
183
|
get exists() {
|
|
156
184
|
return this.file.exists;
|
|
157
185
|
}
|
|
158
186
|
|
|
159
|
-
get
|
|
160
|
-
return this.file.
|
|
187
|
+
get stats() {
|
|
188
|
+
return this.file.stats;
|
|
161
189
|
}
|
|
162
190
|
|
|
163
191
|
delete() {
|
|
164
192
|
this.file.delete();
|
|
165
193
|
}
|
|
194
|
+
|
|
195
|
+
get readStream() {
|
|
196
|
+
return this.file.readStream;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
get writeStream() {
|
|
200
|
+
return this.file.writeStream;
|
|
201
|
+
}
|
|
166
202
|
}
|
|
167
203
|
|
|
168
204
|
/**
|
|
@@ -204,12 +240,12 @@ export class FileTypeNdjson<T extends object> extends FileType {
|
|
|
204
240
|
|
|
205
241
|
append(lines: T | T[]) {
|
|
206
242
|
this.file.append(
|
|
207
|
-
Array.isArray(lines) ? lines.map(
|
|
243
|
+
Array.isArray(lines) ? lines.map(l => JSON.stringify(snapshot(l))) : JSON.stringify(snapshot(lines)),
|
|
208
244
|
);
|
|
209
245
|
}
|
|
210
246
|
|
|
211
247
|
lines() {
|
|
212
|
-
return this.file.lines().map(
|
|
248
|
+
return this.file.lines().map(l => JSON.parse(l) as T);
|
|
213
249
|
}
|
|
214
250
|
}
|
|
215
251
|
|
|
@@ -234,7 +270,7 @@ export class FileTypeCsv<Row extends object> extends FileType {
|
|
|
234
270
|
}
|
|
235
271
|
}
|
|
236
272
|
const headers = Array.from(headerSet);
|
|
237
|
-
const outRows = rows.map(
|
|
273
|
+
const outRows = rows.map(row => headers.map(key => row[key]));
|
|
238
274
|
return finished(writeToStream(this.file.writeStream, [headers, ...outRows]));
|
|
239
275
|
}
|
|
240
276
|
|
|
@@ -261,7 +297,7 @@ export class FileTypeCsv<Row extends object> extends FileType {
|
|
|
261
297
|
),
|
|
262
298
|
);
|
|
263
299
|
})
|
|
264
|
-
.on('error',
|
|
300
|
+
.on('error', e => reject(e))
|
|
265
301
|
.on('end', () => resolve(parsed));
|
|
266
302
|
});
|
|
267
303
|
}
|
package/src/Format.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { format, formatISO, type DateArg } from 'date-fns';
|
|
1
|
+
import { format, formatISO, type DateArg, type Duration } from 'date-fns';
|
|
2
|
+
import formatDuration from 'format-duration';
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* Helpers for formatting dates, times, and numbers as strings
|
|
@@ -6,12 +7,25 @@ import { format, formatISO, type DateArg } from 'date-fns';
|
|
|
6
7
|
export class Format {
|
|
7
8
|
/**
|
|
8
9
|
* date-fns format() with some shortcuts
|
|
9
|
-
* @param formatStr
|
|
10
|
-
*
|
|
10
|
+
* @param formatStr the format to use
|
|
11
|
+
* @param date the date to format, default `new Date()`
|
|
12
|
+
* @example
|
|
13
|
+
* Format.date('iso') // '2026-04-08T13:56:45Z'
|
|
14
|
+
* Format.date('ymd') // '20260408'
|
|
15
|
+
* Format.date('ymd-hm') // '20260408-1356'
|
|
16
|
+
* Format.date('ymd-hms') // '20260408-135645'
|
|
17
|
+
* Format.date('h:m:s') // '13:56:45'
|
|
18
|
+
* @see more format options https://date-fns.org/v4.1.0/docs/format
|
|
11
19
|
*/
|
|
12
|
-
static date(
|
|
20
|
+
static date(
|
|
21
|
+
formatStr: 'iso' | 'ymd' | 'ymd-hm' | 'ymd-hms' | 'h:m:s' | string = 'iso',
|
|
22
|
+
d: DateArg<Date> = new Date(),
|
|
23
|
+
) {
|
|
13
24
|
if (formatStr === 'iso') return formatISO(d);
|
|
14
|
-
if (formatStr === 'ymd') return format(d, '
|
|
25
|
+
if (formatStr === 'ymd') return format(d, 'yyyyMMdd');
|
|
26
|
+
if (formatStr === 'ymd-hm') return format(d, 'yyyyMMdd-HHmm');
|
|
27
|
+
if (formatStr === 'ymd-hms') return format(d, 'yyyyMMdd-HHmmss');
|
|
28
|
+
if (formatStr === 'h:m:s') return format(d, 'HH:mm:ss');
|
|
15
29
|
return format(d, formatStr);
|
|
16
30
|
}
|
|
17
31
|
|
|
@@ -22,10 +36,19 @@ export class Format {
|
|
|
22
36
|
return new Intl.NumberFormat('en-US', { maximumFractionDigits: places }).format(n);
|
|
23
37
|
}
|
|
24
38
|
|
|
39
|
+
static plural(amount: number, singular: string, multiple?: string) {
|
|
40
|
+
return amount === 1 ? `${amount} ${singular}` : `${amount} ${multiple || singular + 's'}`;
|
|
41
|
+
}
|
|
42
|
+
|
|
25
43
|
/**
|
|
26
44
|
* Make millisecond durations actually readable (eg "123ms", "3.56s", "1m 34s", "3h 24m", "2d 4h")
|
|
45
|
+
* @param ms milliseconds
|
|
46
|
+
* @param style 'digital' to output as 'HH:MM:SS'
|
|
47
|
+
* @see details on 'digital' format https://github.com/ungoldman/format-duration
|
|
48
|
+
* @see waiting on `Intl.DurationFormat({ style: 'digital' })` types https://github.com/microsoft/TypeScript/issues/60608
|
|
27
49
|
*/
|
|
28
|
-
static ms(ms: number) {
|
|
50
|
+
static ms(ms: number, style?: 'digital') {
|
|
51
|
+
if (style === 'digital') return formatDuration(ms, { leading: true });
|
|
29
52
|
if (ms < 1000) return `${this.round(ms)}ms`;
|
|
30
53
|
const s = ms / 1000;
|
|
31
54
|
if (s < 60) return `${this.round(s, 2)}s`;
|
package/src/Log.test.ts
CHANGED
|
@@ -3,19 +3,6 @@ import assert from 'node:assert';
|
|
|
3
3
|
import { Log } from './Log.ts';
|
|
4
4
|
|
|
5
5
|
describe('Log', () => {
|
|
6
|
-
it('Throws error', () => {
|
|
7
|
-
try {
|
|
8
|
-
Log.error('Test error');
|
|
9
|
-
} catch (e) {
|
|
10
|
-
return;
|
|
11
|
-
}
|
|
12
|
-
assert(false, 'Did not throw error');
|
|
13
|
-
});
|
|
14
|
-
|
|
15
|
-
it('Recognizes this is a test', () => {
|
|
16
|
-
assert(Log.isTest);
|
|
17
|
-
});
|
|
18
|
-
|
|
19
6
|
it('Uses first argument as message when string', () => {
|
|
20
7
|
const result = Log.prepare('test', { something: 'else' });
|
|
21
8
|
assert(result.message === 'test');
|
package/src/Log.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { inspect } from 'node:util';
|
|
|
2
2
|
import { isObjectLike } from 'lodash-es';
|
|
3
3
|
import chalk, { type ChalkInstance } from 'chalk';
|
|
4
4
|
import { snapshot } from './snapshot.ts';
|
|
5
|
+
import { Format } from './Format.ts';
|
|
5
6
|
|
|
6
7
|
type Severity = 'DEFAULT' | 'DEBUG' | 'INFO' | 'NOTICE' | 'WARNING' | 'ERROR' | 'CRITICAL' | 'ALERT' | 'EMERGENCY';
|
|
7
8
|
|
|
@@ -13,62 +14,70 @@ type Options = {
|
|
|
13
14
|
type Entry = {
|
|
14
15
|
message?: string;
|
|
15
16
|
severity: Severity;
|
|
17
|
+
stack?: string;
|
|
16
18
|
details?: unknown[];
|
|
17
19
|
};
|
|
18
20
|
|
|
19
21
|
export class Log {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
+
static getStack() {
|
|
23
|
+
const details = { stack: '' };
|
|
24
|
+
// replaces details.stack with current stack trace, excluding this Log.getStack call
|
|
25
|
+
Error.captureStackTrace(details, Log.getStack);
|
|
26
|
+
// remove 'Error' on first line
|
|
27
|
+
return details.stack
|
|
28
|
+
.split('\n')
|
|
29
|
+
.map(l => l.trim())
|
|
30
|
+
.filter(l => l !== 'Error');
|
|
31
|
+
}
|
|
22
32
|
|
|
23
33
|
/**
|
|
24
34
|
* Gcloud parses JSON in stdout
|
|
25
35
|
*/
|
|
26
36
|
static #toGcloud(entry: Entry) {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
console.log(JSON.stringify(snapshot(entry)));
|
|
31
|
-
}
|
|
37
|
+
const details = entry.details?.length === 1 ? entry.details[0] : entry.details;
|
|
38
|
+
const output = { ...entry, details, stack: entry.stack || this.getStack() };
|
|
39
|
+
console.log(JSON.stringify(snapshot(output)));
|
|
32
40
|
}
|
|
33
41
|
|
|
34
42
|
/**
|
|
35
43
|
* Includes colors and better inspection for logging during dev
|
|
36
44
|
*/
|
|
37
45
|
static #toConsole(entry: Entry, color: ChalkInstance) {
|
|
38
|
-
if (entry.message) console.log(color(
|
|
39
|
-
entry.details?.forEach(
|
|
46
|
+
if (entry.message) console.log(color(`${Format.date('h:m:s')} [${entry.severity}] ${entry.message}`));
|
|
47
|
+
entry.details?.forEach(detail => {
|
|
40
48
|
console.log(inspect(detail, { depth: 10, breakLength: 100, compact: true, colors: true }));
|
|
41
49
|
});
|
|
42
50
|
}
|
|
43
51
|
|
|
44
|
-
static #log(
|
|
52
|
+
static #log({ severity, color }: Options, ...input: unknown[]) {
|
|
45
53
|
const { message, details } = this.prepare(...input);
|
|
54
|
+
const entry: Entry = { message, severity, details };
|
|
46
55
|
// https://cloud.google.com/run/docs/container-contract#env-vars
|
|
47
56
|
const isGcloud = process.env.K_SERVICE !== undefined || process.env.CLOUD_RUN_JOB !== undefined;
|
|
48
57
|
if (isGcloud) {
|
|
49
|
-
this.#toGcloud(
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
// Hide output while testing this package
|
|
53
|
-
if (!this.isTest) {
|
|
54
|
-
this.#toConsole({ message, severity: options.severity, details }, options.color);
|
|
58
|
+
this.#toGcloud(entry);
|
|
59
|
+
} else {
|
|
60
|
+
this.#toConsole(entry, color);
|
|
55
61
|
}
|
|
56
|
-
return
|
|
62
|
+
return entry;
|
|
57
63
|
}
|
|
58
64
|
|
|
59
65
|
/**
|
|
60
66
|
* Handle first argument being a string or an object with a 'message' prop
|
|
61
67
|
*/
|
|
62
68
|
static prepare(...input: unknown[]): { message?: string; details: unknown[] } {
|
|
63
|
-
let [
|
|
64
|
-
|
|
65
|
-
|
|
69
|
+
let [firstArg, ...rest] = input;
|
|
70
|
+
// First argument is a string, use that as the message
|
|
71
|
+
if (typeof firstArg === 'string') {
|
|
72
|
+
return { message: firstArg, details: rest };
|
|
66
73
|
}
|
|
74
|
+
// First argument is an object with a `message` property
|
|
67
75
|
// @ts-ignore
|
|
68
|
-
if (isObjectLike(
|
|
69
|
-
const { message, ...firstDetails } =
|
|
76
|
+
if (isObjectLike(firstArg) && typeof firstArg['message'] === 'string') {
|
|
77
|
+
const { message, ...firstDetails } = firstArg as { message: string };
|
|
70
78
|
return { message, details: [firstDetails, ...rest] };
|
|
71
79
|
}
|
|
80
|
+
// No message found, log all args as details
|
|
72
81
|
return { details: input };
|
|
73
82
|
}
|
|
74
83
|
|
|
@@ -93,9 +102,6 @@ export class Log {
|
|
|
93
102
|
}
|
|
94
103
|
|
|
95
104
|
static debug(...input: unknown[]) {
|
|
96
|
-
|
|
97
|
-
if (debugging || process.env.NODE_ENV !== 'production') {
|
|
98
|
-
return this.#log({ severity: 'DEBUG', color: chalk.gray }, ...input);
|
|
99
|
-
}
|
|
105
|
+
return this.#log({ severity: 'DEBUG', color: chalk.gray }, ...input);
|
|
100
106
|
}
|
|
101
107
|
}
|