@brianbuie/node-kit 0.10.0 → 0.11.1
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 +116 -48
- package/dist/index.d.mts +44 -16
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +93 -28
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -2
- package/src/Cache.ts +3 -4
- package/src/Dir.test.ts +15 -5
- package/src/Dir.ts +36 -18
- package/src/File.test.ts +1 -1
- package/src/File.ts +1 -1
- package/src/Format.test.ts +34 -0
- package/src/Format.ts +49 -0
- package/src/Log.ts +6 -5
- package/src/index.ts +1 -0
- package/src/snapshot.test.ts +2 -2
- package/tsconfig.json +11 -0
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
# Node Kit
|
|
4
4
|
|
|
5
|
-
Basic tools for
|
|
5
|
+
Basic tools for Node.js projects
|
|
6
6
|
|
|
7
7
|
# Installing
|
|
8
8
|
|
|
@@ -18,7 +18,7 @@ import { Fetcher, Log } from '@brianbuie/node-kit';
|
|
|
18
18
|
|
|
19
19
|
<!--#region ts2md-api-merged-here-->
|
|
20
20
|
|
|
21
|
-
Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types)
|
|
21
|
+
Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types)
|
|
22
22
|
|
|
23
23
|
# Classes
|
|
24
24
|
|
|
@@ -32,11 +32,12 @@ Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types
|
|
|
32
32
|
| [FileTypeCsv](#class-filetypecsv) |
|
|
33
33
|
| [FileTypeJson](#class-filetypejson) |
|
|
34
34
|
| [FileTypeNdjson](#class-filetypendjson) |
|
|
35
|
+
| [Format](#class-format) |
|
|
35
36
|
| [Log](#class-log) |
|
|
36
37
|
| [TempDir](#class-tempdir) |
|
|
37
38
|
| [TypeWriter](#class-typewriter) |
|
|
38
39
|
|
|
39
|
-
Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types)
|
|
40
|
+
Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types)
|
|
40
41
|
|
|
41
42
|
---
|
|
42
43
|
|
|
@@ -59,24 +60,26 @@ export class Cache<T> {
|
|
|
59
60
|
}
|
|
60
61
|
```
|
|
61
62
|
|
|
62
|
-
Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types)
|
|
63
|
+
Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types)
|
|
63
64
|
|
|
64
65
|
---
|
|
65
66
|
## Class: Dir
|
|
66
67
|
|
|
67
|
-
Reference to a specific directory with
|
|
68
|
-
|
|
68
|
+
Reference to a specific directory with methods to create and list files.
|
|
69
|
+
Created immediately if it doesn't exist.
|
|
70
|
+
Default path: './'
|
|
69
71
|
|
|
70
72
|
```ts
|
|
71
73
|
export class Dir {
|
|
72
74
|
path;
|
|
73
|
-
constructor(
|
|
74
|
-
|
|
75
|
+
constructor(inputPath = "./")
|
|
76
|
+
notAbsolute(subPath: string)
|
|
75
77
|
dir(subPath: string)
|
|
76
78
|
tempDir(subPath: string)
|
|
77
|
-
sanitize(
|
|
79
|
+
sanitize(filename: string)
|
|
78
80
|
filepath(base: string)
|
|
79
81
|
file(base: string)
|
|
82
|
+
get files()
|
|
80
83
|
}
|
|
81
84
|
```
|
|
82
85
|
|
|
@@ -87,7 +90,7 @@ export class Dir {
|
|
|
87
90
|
### Constructor
|
|
88
91
|
|
|
89
92
|
```ts
|
|
90
|
-
constructor(
|
|
93
|
+
constructor(inputPath = "./")
|
|
91
94
|
```
|
|
92
95
|
|
|
93
96
|
Argument Details
|
|
@@ -106,15 +109,15 @@ dir(subPath: string)
|
|
|
106
109
|
Argument Details
|
|
107
110
|
|
|
108
111
|
+ **subPath**
|
|
109
|
-
+ to create
|
|
112
|
+
+ relative path to create
|
|
110
113
|
|
|
111
114
|
Example
|
|
112
115
|
|
|
113
116
|
```ts
|
|
114
117
|
const folder = new Dir('example');
|
|
115
|
-
// folder.path = '
|
|
118
|
+
// folder.path = '/absolute/path/to/example'
|
|
116
119
|
const child = folder.dir('path/to/dir');
|
|
117
|
-
// child.path = '
|
|
120
|
+
// child.path = '/absolute/path/to/example/path/to/dir'
|
|
118
121
|
```
|
|
119
122
|
|
|
120
123
|
### Method filepath
|
|
@@ -126,7 +129,7 @@ filepath(base: string)
|
|
|
126
129
|
Argument Details
|
|
127
130
|
|
|
128
131
|
+ **base**
|
|
129
|
-
+ The file name
|
|
132
|
+
+ The file base (name and extension)
|
|
130
133
|
|
|
131
134
|
Example
|
|
132
135
|
|
|
@@ -138,7 +141,7 @@ const filepath = folder.resolve('file.json');
|
|
|
138
141
|
|
|
139
142
|
</details>
|
|
140
143
|
|
|
141
|
-
Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types)
|
|
144
|
+
Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types)
|
|
142
145
|
|
|
143
146
|
---
|
|
144
147
|
## Class: Fetcher
|
|
@@ -236,12 +239,12 @@ See also: [FetchOptions](#type-fetchoptions), [Route](#type-route)
|
|
|
236
239
|
|
|
237
240
|
</details>
|
|
238
241
|
|
|
239
|
-
Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types)
|
|
242
|
+
Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types)
|
|
240
243
|
|
|
241
244
|
---
|
|
242
245
|
## Class: File
|
|
243
246
|
|
|
244
|
-
WARNING: API will change!
|
|
247
|
+
> ⚠️ WARNING: API will change!
|
|
245
248
|
|
|
246
249
|
```ts
|
|
247
250
|
export class File {
|
|
@@ -297,7 +300,7 @@ lines as strings, removes trailing '\n'
|
|
|
297
300
|
|
|
298
301
|
</details>
|
|
299
302
|
|
|
300
|
-
Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types)
|
|
303
|
+
Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types)
|
|
301
304
|
|
|
302
305
|
---
|
|
303
306
|
## Class: FileType
|
|
@@ -314,7 +317,7 @@ export class FileType {
|
|
|
314
317
|
}
|
|
315
318
|
```
|
|
316
319
|
|
|
317
|
-
Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types)
|
|
320
|
+
Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types)
|
|
318
321
|
|
|
319
322
|
---
|
|
320
323
|
## Class: FileTypeCsv
|
|
@@ -333,7 +336,7 @@ export class FileTypeCsv<Row extends object> extends FileType {
|
|
|
333
336
|
|
|
334
337
|
See also: [FileType](#class-filetype)
|
|
335
338
|
|
|
336
|
-
Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types)
|
|
339
|
+
Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types)
|
|
337
340
|
|
|
338
341
|
---
|
|
339
342
|
## Class: FileTypeJson
|
|
@@ -351,7 +354,7 @@ export class FileTypeJson<T> extends FileType {
|
|
|
351
354
|
|
|
352
355
|
See also: [FileType](#class-filetype)
|
|
353
356
|
|
|
354
|
-
Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types)
|
|
357
|
+
Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types)
|
|
355
358
|
|
|
356
359
|
---
|
|
357
360
|
## Class: FileTypeNdjson
|
|
@@ -368,7 +371,58 @@ export class FileTypeNdjson<T extends object> extends FileType {
|
|
|
368
371
|
|
|
369
372
|
See also: [FileType](#class-filetype)
|
|
370
373
|
|
|
371
|
-
Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types)
|
|
374
|
+
Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types)
|
|
375
|
+
|
|
376
|
+
---
|
|
377
|
+
## Class: Format
|
|
378
|
+
|
|
379
|
+
Helpers for formatting dates, times, and numbers as strings
|
|
380
|
+
|
|
381
|
+
```ts
|
|
382
|
+
export class Format {
|
|
383
|
+
static date(formatStr: "iso" | "ymd" | string = "iso", d: DateArg<Date> = new Date())
|
|
384
|
+
static round(n: number, places = 0)
|
|
385
|
+
static ms(ms: number)
|
|
386
|
+
static bytes(b: number)
|
|
387
|
+
}
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
<details>
|
|
391
|
+
|
|
392
|
+
<summary>Class Format Details</summary>
|
|
393
|
+
|
|
394
|
+
### Method date
|
|
395
|
+
|
|
396
|
+
date-fns format() with some shortcuts
|
|
397
|
+
|
|
398
|
+
```ts
|
|
399
|
+
static date(formatStr: "iso" | "ymd" | string = "iso", d: DateArg<Date> = new Date())
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
Argument Details
|
|
403
|
+
|
|
404
|
+
+ **formatStr**
|
|
405
|
+
+ 'iso' to get ISO date, 'ymd' to format as 'yyyy-MM-dd', full options: https://date-fns.org/v4.1.0/docs/format
|
|
406
|
+
|
|
407
|
+
### Method ms
|
|
408
|
+
|
|
409
|
+
Make millisecond durations actually readable (eg "123ms", "3.56s", "1m 34s", "3h 24m", "2d 4h")
|
|
410
|
+
|
|
411
|
+
```ts
|
|
412
|
+
static ms(ms: number)
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
### Method round
|
|
416
|
+
|
|
417
|
+
Round a number to a specific set of places
|
|
418
|
+
|
|
419
|
+
```ts
|
|
420
|
+
static round(n: number, places = 0)
|
|
421
|
+
```
|
|
422
|
+
|
|
423
|
+
</details>
|
|
424
|
+
|
|
425
|
+
Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types)
|
|
372
426
|
|
|
373
427
|
---
|
|
374
428
|
## Class: Log
|
|
@@ -422,7 +476,6 @@ static error(...input: unknown[])
|
|
|
422
476
|
### Method prepare
|
|
423
477
|
|
|
424
478
|
Handle first argument being a string or an object with a 'message' prop
|
|
425
|
-
Also snapshots special objects (eg Error, Response) to keep props in later JSON.stringify output
|
|
426
479
|
|
|
427
480
|
```ts
|
|
428
481
|
static prepare(...input: unknown[]): {
|
|
@@ -433,22 +486,38 @@ static prepare(...input: unknown[]): {
|
|
|
433
486
|
|
|
434
487
|
</details>
|
|
435
488
|
|
|
436
|
-
Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types)
|
|
489
|
+
Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types)
|
|
437
490
|
|
|
438
491
|
---
|
|
439
492
|
## Class: TempDir
|
|
440
493
|
|
|
441
|
-
Extends Dir class with method to `clear()` contents
|
|
494
|
+
Extends Dir class with method to `clear()` contents.
|
|
495
|
+
Default path: `./.${Date.now()}`
|
|
442
496
|
|
|
443
497
|
```ts
|
|
444
498
|
export class TempDir extends Dir {
|
|
499
|
+
constructor(inputPath = `./.${Date.now()}`)
|
|
445
500
|
clear()
|
|
446
501
|
}
|
|
447
502
|
```
|
|
448
503
|
|
|
449
504
|
See also: [Dir](#class-dir)
|
|
450
505
|
|
|
451
|
-
|
|
506
|
+
<details>
|
|
507
|
+
|
|
508
|
+
<summary>Class TempDir Details</summary>
|
|
509
|
+
|
|
510
|
+
### Method clear
|
|
511
|
+
|
|
512
|
+
> ⚠️ Warning! This deletes the directory, make sure it's not
|
|
513
|
+
|
|
514
|
+
```ts
|
|
515
|
+
clear()
|
|
516
|
+
```
|
|
517
|
+
|
|
518
|
+
</details>
|
|
519
|
+
|
|
520
|
+
Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types)
|
|
452
521
|
|
|
453
522
|
---
|
|
454
523
|
## Class: TypeWriter
|
|
@@ -482,7 +551,7 @@ async toString()
|
|
|
482
551
|
|
|
483
552
|
</details>
|
|
484
553
|
|
|
485
|
-
Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types)
|
|
554
|
+
Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types)
|
|
486
555
|
|
|
487
556
|
---
|
|
488
557
|
# Functions
|
|
@@ -490,9 +559,10 @@ Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types
|
|
|
490
559
|
| |
|
|
491
560
|
| --- |
|
|
492
561
|
| [snapshot](#function-snapshot) |
|
|
562
|
+
| [temp](#function-temp) |
|
|
493
563
|
| [timeout](#function-timeout) |
|
|
494
564
|
|
|
495
|
-
Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types)
|
|
565
|
+
Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types)
|
|
496
566
|
|
|
497
567
|
---
|
|
498
568
|
|
|
@@ -505,7 +575,18 @@ functions are removed
|
|
|
505
575
|
export function snapshot(i: unknown, max = 50, depth = 0): any
|
|
506
576
|
```
|
|
507
577
|
|
|
508
|
-
Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types)
|
|
578
|
+
Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types)
|
|
579
|
+
|
|
580
|
+
---
|
|
581
|
+
## Function: temp
|
|
582
|
+
|
|
583
|
+
Creates a '.temp' directory in current working directory
|
|
584
|
+
|
|
585
|
+
```ts
|
|
586
|
+
export function temp()
|
|
587
|
+
```
|
|
588
|
+
|
|
589
|
+
Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types)
|
|
509
590
|
|
|
510
591
|
---
|
|
511
592
|
## Function: timeout
|
|
@@ -514,7 +595,7 @@ Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types
|
|
|
514
595
|
export async function timeout(ms: number)
|
|
515
596
|
```
|
|
516
597
|
|
|
517
|
-
Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types)
|
|
598
|
+
Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types)
|
|
518
599
|
|
|
519
600
|
---
|
|
520
601
|
# Types
|
|
@@ -525,7 +606,7 @@ Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types
|
|
|
525
606
|
| [Query](#type-query) |
|
|
526
607
|
| [Route](#type-route) |
|
|
527
608
|
|
|
528
|
-
Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types)
|
|
609
|
+
Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types)
|
|
529
610
|
|
|
530
611
|
---
|
|
531
612
|
|
|
@@ -545,7 +626,7 @@ export type FetchOptions = RequestInit & {
|
|
|
545
626
|
|
|
546
627
|
See also: [Query](#type-query), [timeout](#function-timeout)
|
|
547
628
|
|
|
548
|
-
Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types)
|
|
629
|
+
Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types)
|
|
549
630
|
|
|
550
631
|
---
|
|
551
632
|
## Type: Query
|
|
@@ -554,7 +635,7 @@ Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types
|
|
|
554
635
|
export type Query = Record<string, QueryVal | QueryVal[]>
|
|
555
636
|
```
|
|
556
637
|
|
|
557
|
-
Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types)
|
|
638
|
+
Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types)
|
|
558
639
|
|
|
559
640
|
---
|
|
560
641
|
## Type: Route
|
|
@@ -563,21 +644,8 @@ Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types
|
|
|
563
644
|
export type Route = string | URL
|
|
564
645
|
```
|
|
565
646
|
|
|
566
|
-
Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types)
|
|
567
|
-
|
|
568
|
-
---
|
|
569
|
-
# Variables
|
|
570
|
-
|
|
571
|
-
## Variable: temp
|
|
572
|
-
|
|
573
|
-
```ts
|
|
574
|
-
temp = new TempDir(".temp")
|
|
575
|
-
```
|
|
576
|
-
|
|
577
|
-
See also: [TempDir](#class-tempdir)
|
|
578
|
-
|
|
579
|
-
Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types), [Variables](#variables)
|
|
647
|
+
Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types)
|
|
580
648
|
|
|
581
649
|
---
|
|
582
650
|
|
|
583
|
-
<!--#endregion ts2md-api-merged-here-->
|
|
651
|
+
<!--#endregion ts2md-api-merged-here-->
|
package/dist/index.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as fs from "node:fs";
|
|
2
2
|
import { Readable } from "node:stream";
|
|
3
|
-
import { Duration } from "date-fns";
|
|
3
|
+
import { DateArg, Duration } from "date-fns";
|
|
4
4
|
import { ChalkInstance } from "chalk";
|
|
5
5
|
import * as qt from "quicktype-core";
|
|
6
6
|
import * as quicktype_core_dist_TargetLanguage_js0 from "quicktype-core/dist/TargetLanguage.js";
|
|
@@ -15,7 +15,7 @@ import * as quicktype_core_dist_language_Smithy4s_language_js0 from "quicktype-c
|
|
|
15
15
|
|
|
16
16
|
//#region src/File.d.ts
|
|
17
17
|
/**
|
|
18
|
-
* WARNING: API will change!
|
|
18
|
+
* > ⚠️ WARNING: API will change!
|
|
19
19
|
*/
|
|
20
20
|
declare class File {
|
|
21
21
|
path: string;
|
|
@@ -90,30 +90,31 @@ declare class FileTypeCsv<Row extends object> extends FileType {
|
|
|
90
90
|
//#endregion
|
|
91
91
|
//#region src/Dir.d.ts
|
|
92
92
|
/**
|
|
93
|
-
* Reference to a specific directory with
|
|
94
|
-
*
|
|
93
|
+
* Reference to a specific directory with methods to create and list files.
|
|
94
|
+
* Created immediately if it doesn't exist.
|
|
95
|
+
* Default path: './'
|
|
95
96
|
*/
|
|
96
97
|
declare class Dir {
|
|
97
98
|
path: string;
|
|
98
99
|
/**
|
|
99
100
|
* @param path can be relative to workspace or absolute
|
|
100
101
|
*/
|
|
101
|
-
constructor(
|
|
102
|
-
|
|
102
|
+
constructor(inputPath?: string);
|
|
103
|
+
notAbsolute(subPath: string): string;
|
|
103
104
|
/**
|
|
104
105
|
* Create a new Dir inside the current Dir
|
|
105
|
-
* @param subPath to create
|
|
106
|
+
* @param subPath relative path to create
|
|
106
107
|
* @example
|
|
107
108
|
* const folder = new Dir('example');
|
|
108
|
-
* // folder.path = '
|
|
109
|
+
* // folder.path = '/absolute/path/to/example'
|
|
109
110
|
* const child = folder.dir('path/to/dir');
|
|
110
|
-
* // child.path = '
|
|
111
|
+
* // child.path = '/absolute/path/to/example/path/to/dir'
|
|
111
112
|
*/
|
|
112
113
|
dir(subPath: string): Dir;
|
|
113
114
|
tempDir(subPath: string): TempDir;
|
|
114
|
-
sanitize(
|
|
115
|
+
sanitize(filename: string): string;
|
|
115
116
|
/**
|
|
116
|
-
* @param base - The file name
|
|
117
|
+
* @param base - The file base (name and extension)
|
|
117
118
|
* @example
|
|
118
119
|
* const folder = new Dir('example');
|
|
119
120
|
* const filepath = folder.resolve('file.json');
|
|
@@ -121,17 +122,23 @@ declare class Dir {
|
|
|
121
122
|
*/
|
|
122
123
|
filepath(base: string): string;
|
|
123
124
|
file(base: string): File;
|
|
125
|
+
get files(): File[];
|
|
124
126
|
}
|
|
125
127
|
/**
|
|
126
|
-
* Extends Dir class with method to `clear()` contents
|
|
128
|
+
* Extends Dir class with method to `clear()` contents.
|
|
129
|
+
* Default path: `./.${Date.now()}`
|
|
127
130
|
*/
|
|
128
131
|
declare class TempDir extends Dir {
|
|
132
|
+
constructor(inputPath?: string);
|
|
133
|
+
/**
|
|
134
|
+
* > ⚠️ Warning! This deletes the directory, make sure it's not
|
|
135
|
+
*/
|
|
129
136
|
clear(): void;
|
|
130
137
|
}
|
|
131
138
|
/**
|
|
132
|
-
*
|
|
139
|
+
* Creates a '.temp' directory in current working directory
|
|
133
140
|
*/
|
|
134
|
-
declare
|
|
141
|
+
declare function temp(): TempDir;
|
|
135
142
|
//#endregion
|
|
136
143
|
//#region src/Cache.d.ts
|
|
137
144
|
/**
|
|
@@ -216,6 +223,28 @@ declare class Fetcher {
|
|
|
216
223
|
fetchJson<T>(route: Route, opts?: FetchOptions): Promise<[T, Response, Request]>;
|
|
217
224
|
}
|
|
218
225
|
//#endregion
|
|
226
|
+
//#region src/Format.d.ts
|
|
227
|
+
/**
|
|
228
|
+
* Helpers for formatting dates, times, and numbers as strings
|
|
229
|
+
*/
|
|
230
|
+
declare class Format {
|
|
231
|
+
/**
|
|
232
|
+
* date-fns format() with some shortcuts
|
|
233
|
+
* @param formatStr
|
|
234
|
+
* 'iso' to get ISO date, 'ymd' to format as 'yyyy-MM-dd', full options: https://date-fns.org/v4.1.0/docs/format
|
|
235
|
+
*/
|
|
236
|
+
static date(formatStr?: 'iso' | 'ymd' | string, d?: DateArg<Date>): string;
|
|
237
|
+
/**
|
|
238
|
+
* Round a number to a specific set of places
|
|
239
|
+
*/
|
|
240
|
+
static round(n: number, places?: number): string;
|
|
241
|
+
/**
|
|
242
|
+
* Make millisecond durations actually readable (eg "123ms", "3.56s", "1m 34s", "3h 24m", "2d 4h")
|
|
243
|
+
*/
|
|
244
|
+
static ms(ms: number): string;
|
|
245
|
+
static bytes(b: number): string;
|
|
246
|
+
}
|
|
247
|
+
//#endregion
|
|
219
248
|
//#region src/Log.d.ts
|
|
220
249
|
type Severity = 'DEFAULT' | 'DEBUG' | 'INFO' | 'NOTICE' | 'WARNING' | 'ERROR' | 'CRITICAL' | 'ALERT' | 'EMERGENCY';
|
|
221
250
|
type Options = {
|
|
@@ -227,7 +256,6 @@ declare class Log {
|
|
|
227
256
|
static isTest: boolean;
|
|
228
257
|
/**
|
|
229
258
|
* Handle first argument being a string or an object with a 'message' prop
|
|
230
|
-
* Also snapshots special objects (eg Error, Response) to keep props in later JSON.stringify output
|
|
231
259
|
*/
|
|
232
260
|
static prepare(...input: unknown[]): {
|
|
233
261
|
message?: string;
|
|
@@ -722,5 +750,5 @@ declare class TypeWriter {
|
|
|
722
750
|
toFile(): Promise<void>;
|
|
723
751
|
}
|
|
724
752
|
//#endregion
|
|
725
|
-
export { Cache, Dir, type FetchOptions, Fetcher, File, FileType, FileTypeCsv, FileTypeJson, FileTypeNdjson, Log, type Query, type Route, TempDir, TypeWriter, snapshot, temp, timeout };
|
|
753
|
+
export { Cache, Dir, type FetchOptions, Fetcher, File, FileType, FileTypeCsv, FileTypeJson, FileTypeNdjson, Format, Log, type Query, type Route, TempDir, TypeWriter, snapshot, temp, timeout };
|
|
726
754
|
//# sourceMappingURL=index.d.mts.map
|
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/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
|
@@ -5,7 +5,7 @@ import { Readable } from "node:stream";
|
|
|
5
5
|
import { finished } from "node:stream/promises";
|
|
6
6
|
import { parseStream, writeToStream } from "fast-csv";
|
|
7
7
|
import { isObjectLike, merge } from "lodash-es";
|
|
8
|
-
import { add, isAfter } from "date-fns";
|
|
8
|
+
import { add, format, formatISO, isAfter } from "date-fns";
|
|
9
9
|
import extractDomain from "extract-domain";
|
|
10
10
|
import { inspect } from "node:util";
|
|
11
11
|
import chalk from "chalk";
|
|
@@ -40,7 +40,7 @@ function snapshot(i, max = 50, depth = 0) {
|
|
|
40
40
|
//#endregion
|
|
41
41
|
//#region src/File.ts
|
|
42
42
|
/**
|
|
43
|
-
* WARNING: API will change!
|
|
43
|
+
* > ⚠️ WARNING: API will change!
|
|
44
44
|
*/
|
|
45
45
|
var File = class {
|
|
46
46
|
path;
|
|
@@ -211,40 +211,43 @@ var FileTypeCsv = class extends FileType {
|
|
|
211
211
|
//#endregion
|
|
212
212
|
//#region src/Dir.ts
|
|
213
213
|
/**
|
|
214
|
-
* Reference to a specific directory with
|
|
215
|
-
*
|
|
214
|
+
* Reference to a specific directory with methods to create and list files.
|
|
215
|
+
* Created immediately if it doesn't exist.
|
|
216
|
+
* Default path: './'
|
|
216
217
|
*/
|
|
217
218
|
var Dir = class Dir {
|
|
218
219
|
path;
|
|
219
220
|
/**
|
|
220
221
|
* @param path can be relative to workspace or absolute
|
|
221
222
|
*/
|
|
222
|
-
constructor(
|
|
223
|
-
this.path = path.resolve(
|
|
224
|
-
}
|
|
225
|
-
create() {
|
|
223
|
+
constructor(inputPath = "./") {
|
|
224
|
+
this.path = path.resolve(inputPath);
|
|
226
225
|
fs.mkdirSync(this.path, { recursive: true });
|
|
227
226
|
}
|
|
227
|
+
notAbsolute(subPath) {
|
|
228
|
+
if (path.isAbsolute(subPath)) throw new Error(`Absolute path provided: "${subPath}"`);
|
|
229
|
+
return subPath;
|
|
230
|
+
}
|
|
228
231
|
/**
|
|
229
232
|
* Create a new Dir inside the current Dir
|
|
230
|
-
* @param subPath to create
|
|
233
|
+
* @param subPath relative path to create
|
|
231
234
|
* @example
|
|
232
235
|
* const folder = new Dir('example');
|
|
233
|
-
* // folder.path = '
|
|
236
|
+
* // folder.path = '/absolute/path/to/example'
|
|
234
237
|
* const child = folder.dir('path/to/dir');
|
|
235
|
-
* // child.path = '
|
|
238
|
+
* // child.path = '/absolute/path/to/example/path/to/dir'
|
|
236
239
|
*/
|
|
237
240
|
dir(subPath) {
|
|
238
|
-
return new Dir(path.resolve(this.path, subPath));
|
|
241
|
+
return new Dir(path.resolve(this.path, this.notAbsolute(subPath)));
|
|
239
242
|
}
|
|
240
243
|
tempDir(subPath) {
|
|
241
|
-
return new TempDir(path.resolve(this.path, subPath));
|
|
244
|
+
return new TempDir(path.resolve(this.path, this.notAbsolute(subPath)));
|
|
242
245
|
}
|
|
243
|
-
sanitize(
|
|
244
|
-
return sanitizeFilename(
|
|
246
|
+
sanitize(filename) {
|
|
247
|
+
return sanitizeFilename(filename.replace("https://", "").replace("www.", ""), { replacement: "_" }).slice(-200);
|
|
245
248
|
}
|
|
246
249
|
/**
|
|
247
|
-
* @param base - The file name
|
|
250
|
+
* @param base - The file base (name and extension)
|
|
248
251
|
* @example
|
|
249
252
|
* const folder = new Dir('example');
|
|
250
253
|
* const filepath = folder.resolve('file.json');
|
|
@@ -256,27 +259,38 @@ var Dir = class Dir {
|
|
|
256
259
|
file(base) {
|
|
257
260
|
return new File(this.filepath(base));
|
|
258
261
|
}
|
|
262
|
+
get files() {
|
|
263
|
+
return fs.readdirSync(this.path).map((filename) => this.file(filename));
|
|
264
|
+
}
|
|
259
265
|
};
|
|
260
266
|
/**
|
|
261
|
-
* Extends Dir class with method to `clear()` contents
|
|
267
|
+
* Extends Dir class with method to `clear()` contents.
|
|
268
|
+
* Default path: `./.${Date.now()}`
|
|
262
269
|
*/
|
|
263
270
|
var TempDir = class extends Dir {
|
|
271
|
+
constructor(inputPath = `./.${Date.now()}`) {
|
|
272
|
+
super(inputPath);
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* > ⚠️ Warning! This deletes the directory, make sure it's not
|
|
276
|
+
*/
|
|
264
277
|
clear() {
|
|
265
278
|
fs.rmSync(this.path, {
|
|
266
279
|
recursive: true,
|
|
267
280
|
force: true
|
|
268
281
|
});
|
|
269
|
-
this.
|
|
282
|
+
fs.mkdirSync(this.path, { recursive: true });
|
|
270
283
|
}
|
|
271
284
|
};
|
|
272
285
|
/**
|
|
273
|
-
*
|
|
286
|
+
* Creates a '.temp' directory in current working directory
|
|
274
287
|
*/
|
|
275
|
-
|
|
288
|
+
function temp() {
|
|
289
|
+
return new TempDir(".temp");
|
|
290
|
+
}
|
|
276
291
|
|
|
277
292
|
//#endregion
|
|
278
293
|
//#region src/Cache.ts
|
|
279
|
-
const cacheDir = temp.dir("cache");
|
|
280
294
|
/**
|
|
281
295
|
* Save data to a local file with an expiration.
|
|
282
296
|
* Fresh/stale data is returned with a flag for if it's fresh or not,
|
|
@@ -286,7 +300,7 @@ var Cache = class {
|
|
|
286
300
|
file;
|
|
287
301
|
ttl;
|
|
288
302
|
constructor(key, ttl, initialData) {
|
|
289
|
-
this.file =
|
|
303
|
+
this.file = new TempDir(".cache").file(key).json();
|
|
290
304
|
this.ttl = typeof ttl === "number" ? { minutes: ttl } : ttl;
|
|
291
305
|
if (initialData) this.write(initialData);
|
|
292
306
|
}
|
|
@@ -409,6 +423,58 @@ var Fetcher = class {
|
|
|
409
423
|
}
|
|
410
424
|
};
|
|
411
425
|
|
|
426
|
+
//#endregion
|
|
427
|
+
//#region src/Format.ts
|
|
428
|
+
/**
|
|
429
|
+
* Helpers for formatting dates, times, and numbers as strings
|
|
430
|
+
*/
|
|
431
|
+
var Format = class {
|
|
432
|
+
/**
|
|
433
|
+
* date-fns format() with some shortcuts
|
|
434
|
+
* @param formatStr
|
|
435
|
+
* 'iso' to get ISO date, 'ymd' to format as 'yyyy-MM-dd', full options: https://date-fns.org/v4.1.0/docs/format
|
|
436
|
+
*/
|
|
437
|
+
static date(formatStr = "iso", d = /* @__PURE__ */ new Date()) {
|
|
438
|
+
if (formatStr === "iso") return formatISO(d);
|
|
439
|
+
if (formatStr === "ymd") return format(d, "yyyy-MM-dd");
|
|
440
|
+
return format(d, formatStr);
|
|
441
|
+
}
|
|
442
|
+
/**
|
|
443
|
+
* Round a number to a specific set of places
|
|
444
|
+
*/
|
|
445
|
+
static round(n, places = 0) {
|
|
446
|
+
return new Intl.NumberFormat("en-US", { maximumFractionDigits: places }).format(n);
|
|
447
|
+
}
|
|
448
|
+
/**
|
|
449
|
+
* Make millisecond durations actually readable (eg "123ms", "3.56s", "1m 34s", "3h 24m", "2d 4h")
|
|
450
|
+
*/
|
|
451
|
+
static ms(ms) {
|
|
452
|
+
if (ms < 1e3) return `${this.round(ms)}ms`;
|
|
453
|
+
const s = ms / 1e3;
|
|
454
|
+
if (s < 60) return `${this.round(s, 2)}s`;
|
|
455
|
+
const m = Math.floor(s / 60);
|
|
456
|
+
if (m < 60) return `${m}m ${Math.floor(s) % 60}s`;
|
|
457
|
+
const h = Math.floor(m / 60);
|
|
458
|
+
if (h < 24) return `${h}h ${m % 60}m`;
|
|
459
|
+
return `${Math.floor(h / 24)}d ${h % 24}h`;
|
|
460
|
+
}
|
|
461
|
+
static bytes(b) {
|
|
462
|
+
const labels = [
|
|
463
|
+
"b",
|
|
464
|
+
"KB",
|
|
465
|
+
"MB",
|
|
466
|
+
"GB",
|
|
467
|
+
"TB"
|
|
468
|
+
];
|
|
469
|
+
let factor = 0;
|
|
470
|
+
while (b >= 1024 && labels[factor + 1]) {
|
|
471
|
+
b = b / 1024;
|
|
472
|
+
factor++;
|
|
473
|
+
}
|
|
474
|
+
return `${this.round(b, 2)} ${labels[factor]}`;
|
|
475
|
+
}
|
|
476
|
+
};
|
|
477
|
+
|
|
412
478
|
//#endregion
|
|
413
479
|
//#region src/Log.ts
|
|
414
480
|
var Log = class {
|
|
@@ -417,11 +483,11 @@ var Log = class {
|
|
|
417
483
|
* Gcloud parses JSON in stdout
|
|
418
484
|
*/
|
|
419
485
|
static #toGcloud(entry) {
|
|
420
|
-
if (entry.details?.length === 1) console.log(JSON.stringify({
|
|
486
|
+
if (entry.details?.length === 1) console.log(JSON.stringify(snapshot({
|
|
421
487
|
...entry,
|
|
422
488
|
details: entry.details[0]
|
|
423
|
-
}));
|
|
424
|
-
else console.log(JSON.stringify(entry));
|
|
489
|
+
})));
|
|
490
|
+
else console.log(JSON.stringify(snapshot(entry)));
|
|
425
491
|
}
|
|
426
492
|
/**
|
|
427
493
|
* Includes colors and better inspection for logging during dev
|
|
@@ -464,10 +530,9 @@ var Log = class {
|
|
|
464
530
|
}
|
|
465
531
|
/**
|
|
466
532
|
* Handle first argument being a string or an object with a 'message' prop
|
|
467
|
-
* Also snapshots special objects (eg Error, Response) to keep props in later JSON.stringify output
|
|
468
533
|
*/
|
|
469
534
|
static prepare(...input) {
|
|
470
|
-
let [first, ...rest] = input
|
|
535
|
+
let [first, ...rest] = input;
|
|
471
536
|
if (typeof first === "string") return {
|
|
472
537
|
message: first,
|
|
473
538
|
details: rest
|
|
@@ -569,5 +634,5 @@ var TypeWriter = class {
|
|
|
569
634
|
};
|
|
570
635
|
|
|
571
636
|
//#endregion
|
|
572
|
-
export { Cache, Dir, Fetcher, File, FileType, FileTypeCsv, FileTypeJson, FileTypeNdjson, Log, TempDir, TypeWriter, snapshot, temp, timeout };
|
|
637
|
+
export { Cache, Dir, Fetcher, File, FileType, FileTypeCsv, FileTypeJson, FileTypeNdjson, Format, Log, TempDir, TypeWriter, snapshot, temp, timeout };
|
|
573
638
|
//# sourceMappingURL=index.mjs.map
|
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","params: [string, string][]","timeout","#toGcloud","#toConsole","#log"],"sources":["../src/snapshot.ts","../src/File.ts","../src/Dir.ts","../src/Cache.ts","../src/Fetcher.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 { writeToStream, parseStream } from 'fast-csv';\nimport { snapshot } from './snapshot.ts';\n\n/**\n * WARNING: API will change!\n */\nexport class File {\n path;\n root;\n dir;\n base;\n ext;\n name;\n\n constructor(filepath: string) {\n this.path = filepath;\n const { root, dir, base, ext, name } = path.parse(filepath);\n this.root = root;\n this.dir = dir;\n this.base = base;\n this.ext = ext;\n this.name = name;\n }\n\n get exists() {\n return fs.existsSync(this.path);\n }\n\n delete() {\n fs.rmSync(this.path, { force: true });\n }\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.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(path.parse(this.path).dir, { recursive: true });\n return fs.createWriteStream(this.path);\n }\n\n write(contents: string | ReadableStream) {\n fs.mkdirSync(path.parse(this.path).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 static get FileType() {\n return FileType;\n }\n\n json<T>(contents?: T) {\n return new FileTypeJson<T>(this.path, contents);\n }\n\n static get json() {\n return FileTypeJson;\n }\n\n ndjson<T extends object>(lines?: T | T[]) {\n return new FileTypeNdjson<T>(this.path, lines);\n }\n\n static get ndjson() {\n return FileTypeNdjson;\n }\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 unsafe! Type is not checked at runtime, avoid using on files manipulated outside of your application.\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('error', (e) => reject(e))\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('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 helpful methods for resolving filepaths,\n * sanitizing filenames, and saving files.\n */\nexport class Dir {\n path;\n\n /**\n * @param path can be relative to workspace or absolute\n */\n constructor(_path = './') {\n this.path = path.resolve(_path);\n }\n\n create() {\n fs.mkdirSync(this.path, { recursive: true });\n }\n\n /**\n * Create a new Dir inside the current Dir\n * @param subPath to create in current Dir\n * @example\n * const folder = new Dir('example');\n * // folder.path = './example'\n * const child = folder.dir('path/to/dir');\n * // child.path = './example/path/to/dir'\n */\n dir(subPath: string) {\n return new Dir(path.resolve(this.path, subPath));\n }\n\n tempDir(subPath: string) {\n return new TempDir(path.resolve(this.path, subPath));\n }\n\n sanitize(name: string) {\n return sanitizeFilename(name.replace('https://', '').replace('www.', ''), { replacement: '_' }).slice(-200);\n }\n\n /**\n * @param base - The file name with 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\n/**\n * Extends Dir class with method to `clear()` contents\n */\nexport class TempDir extends Dir {\n clear() {\n fs.rmSync(this.path, { recursive: true, force: true });\n this.create();\n }\n}\n\n/**\n * Common temp dir location\n */\nexport const temp = new TempDir('.temp');\n","import { type Duration, isAfter, add } from 'date-fns';\nimport { temp } from './Dir.ts';\n\nconst cacheDir = temp.dir('cache');\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 this.file = cacheDir.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 { 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({ ...entry, details: entry.details[0] }));\n } else {\n console.log(JSON.stringify(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 * Also snapshots special objects (eg Error, Response) to keep props in later JSON.stringify output\n */\n static prepare(...input: unknown[]): { message?: string; details: unknown[] } {\n let [first, ...rest] = input.map((i) => snapshot(i));\n if (typeof first === 'string') return { message: first, details: rest };\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","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 { writeToStream, parseStream } from 'fast-csv';\nimport { snapshot } from './snapshot.ts';\n\n/**\n * > ⚠️ WARNING: API will change!\n */\nexport class File {\n path;\n root;\n dir;\n base;\n ext;\n name;\n\n constructor(filepath: string) {\n this.path = filepath;\n const { root, dir, base, ext, name } = path.parse(filepath);\n this.root = root;\n this.dir = dir;\n this.base = base;\n this.ext = ext;\n this.name = name;\n }\n\n get exists() {\n return fs.existsSync(this.path);\n }\n\n delete() {\n fs.rmSync(this.path, { force: true });\n }\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.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(path.parse(this.path).dir, { recursive: true });\n return fs.createWriteStream(this.path);\n }\n\n write(contents: string | ReadableStream) {\n fs.mkdirSync(path.parse(this.path).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 static get FileType() {\n return FileType;\n }\n\n json<T>(contents?: T) {\n return new FileTypeJson<T>(this.path, contents);\n }\n\n static get json() {\n return FileTypeJson;\n }\n\n ndjson<T extends object>(lines?: T | T[]) {\n return new FileTypeNdjson<T>(this.path, lines);\n }\n\n static get ndjson() {\n return FileTypeNdjson;\n }\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 unsafe! Type is not checked at runtime, avoid using on files manipulated outside of your application.\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('error', (e) => reject(e))\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('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 * Created immediately if it doesn't exist.\n * Default path: './'\n */\nexport class Dir {\n path;\n\n /**\n * @param path can be relative to workspace or absolute\n */\n constructor(inputPath = './') {\n this.path = path.resolve(inputPath);\n fs.mkdirSync(this.path, { recursive: true });\n }\n\n notAbsolute(subPath: string) {\n if (path.isAbsolute(subPath)) throw new Error(`Absolute path provided: \"${subPath}\"`);\n return subPath;\n }\n\n /**\n * Create a new Dir inside the current Dir\n * @param subPath relative path to create\n * @example\n * const folder = new Dir('example');\n * // folder.path = '/absolute/path/to/example'\n * const child = folder.dir('path/to/dir');\n * // child.path = '/absolute/path/to/example/path/to/dir'\n */\n dir(subPath: string) {\n return new Dir(path.resolve(this.path, this.notAbsolute(subPath)));\n }\n\n tempDir(subPath: string) {\n return new TempDir(path.resolve(this.path, this.notAbsolute(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: `./.${Date.now()}`\n */\nexport class TempDir extends Dir {\n constructor(inputPath = `./.${Date.now()}`) {\n super(inputPath);\n }\n\n /**\n * > ⚠️ Warning! This deletes the directory, make sure it's not\n */\n clear() {\n fs.rmSync(this.path, { recursive: true, force: true });\n fs.mkdirSync(this.path, { recursive: true });\n }\n}\n\n/**\n * Creates a '.temp' directory in current working directory\n */\nexport function temp() {\n return new TempDir('.temp');\n}\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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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@brianbuie/node-kit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.1",
|
|
4
4
|
"license": "ISC",
|
|
5
|
+
"description": "Basic tools for Node.js projects",
|
|
6
|
+
"author": "Brian Buie <brian@buie.dev>",
|
|
5
7
|
"repository": {
|
|
6
8
|
"type": "git",
|
|
7
9
|
"url": "git+https://github.com/brianbuie/node-kit.git"
|
|
@@ -22,7 +24,7 @@
|
|
|
22
24
|
"files": [
|
|
23
25
|
"src",
|
|
24
26
|
"dist",
|
|
25
|
-
"
|
|
27
|
+
"tsconfig.json"
|
|
26
28
|
],
|
|
27
29
|
"engines": {
|
|
28
30
|
"node": ">=24"
|
package/src/Cache.ts
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import { type Duration, isAfter, add } from 'date-fns';
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
const cacheDir = temp.dir('cache');
|
|
2
|
+
import { TempDir } from './Dir.ts';
|
|
5
3
|
|
|
6
4
|
/**
|
|
7
5
|
* Save data to a local file with an expiration.
|
|
@@ -13,7 +11,8 @@ export class Cache<T> {
|
|
|
13
11
|
ttl;
|
|
14
12
|
|
|
15
13
|
constructor(key: string, ttl: number | Duration, initialData?: T) {
|
|
16
|
-
|
|
14
|
+
const dir = new TempDir('.cache');
|
|
15
|
+
this.file = dir.file(key).json<{ savedAt: string; data: T }>();
|
|
17
16
|
this.ttl = typeof ttl === 'number' ? { minutes: ttl } : ttl;
|
|
18
17
|
if (initialData) this.write(initialData);
|
|
19
18
|
}
|
package/src/Dir.test.ts
CHANGED
|
@@ -3,7 +3,7 @@ import assert from 'node:assert';
|
|
|
3
3
|
import { Dir, TempDir, temp } from './Dir.ts';
|
|
4
4
|
|
|
5
5
|
describe('Dir', () => {
|
|
6
|
-
const testDir = temp.dir('dir-test');
|
|
6
|
+
const testDir = temp().dir('dir-test');
|
|
7
7
|
|
|
8
8
|
it('Sanitizes filenames', () => {
|
|
9
9
|
const name = testDir.sanitize(':/something/else.json');
|
|
@@ -18,14 +18,24 @@ describe('Dir', () => {
|
|
|
18
18
|
assert(sub.path.includes(subPath));
|
|
19
19
|
});
|
|
20
20
|
|
|
21
|
-
it('
|
|
22
|
-
const sub = temp.tempDir('example');
|
|
21
|
+
it('.tempDir returns instance of TempDir', () => {
|
|
22
|
+
const sub = temp().tempDir('example');
|
|
23
23
|
assert(sub instanceof TempDir);
|
|
24
24
|
});
|
|
25
25
|
|
|
26
|
+
it('.dir() and .tempDir() throw on absolute path input', () => {
|
|
27
|
+
const t = temp();
|
|
28
|
+
assert.throws(() => {
|
|
29
|
+
t.dir(t.path);
|
|
30
|
+
});
|
|
31
|
+
assert.throws(() => {
|
|
32
|
+
t.tempDir(t.path);
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
|
|
26
36
|
it('Resolves filenames in folder', () => {
|
|
27
|
-
const txt = temp.filepath('test.txt');
|
|
28
|
-
assert(txt.includes(temp.path));
|
|
37
|
+
const txt = temp().filepath('test.txt');
|
|
38
|
+
assert(txt.includes(temp().path));
|
|
29
39
|
assert(txt.includes('test.txt'));
|
|
30
40
|
});
|
|
31
41
|
});
|
package/src/Dir.ts
CHANGED
|
@@ -4,8 +4,9 @@ import sanitizeFilename from 'sanitize-filename';
|
|
|
4
4
|
import { File } from './File.ts';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
|
-
* Reference to a specific directory with
|
|
8
|
-
*
|
|
7
|
+
* Reference to a specific directory with methods to create and list files.
|
|
8
|
+
* Created immediately if it doesn't exist.
|
|
9
|
+
* Default path: './'
|
|
9
10
|
*/
|
|
10
11
|
export class Dir {
|
|
11
12
|
path;
|
|
@@ -13,37 +14,40 @@ export class Dir {
|
|
|
13
14
|
/**
|
|
14
15
|
* @param path can be relative to workspace or absolute
|
|
15
16
|
*/
|
|
16
|
-
constructor(
|
|
17
|
-
this.path = path.resolve(
|
|
17
|
+
constructor(inputPath = './') {
|
|
18
|
+
this.path = path.resolve(inputPath);
|
|
19
|
+
fs.mkdirSync(this.path, { recursive: true });
|
|
18
20
|
}
|
|
19
21
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
+
notAbsolute(subPath: string) {
|
|
23
|
+
if (path.isAbsolute(subPath)) throw new Error(`Absolute path provided: "${subPath}"`);
|
|
24
|
+
return subPath;
|
|
22
25
|
}
|
|
23
26
|
|
|
24
27
|
/**
|
|
25
28
|
* Create a new Dir inside the current Dir
|
|
26
|
-
* @param subPath to create
|
|
29
|
+
* @param subPath relative path to create
|
|
27
30
|
* @example
|
|
28
31
|
* const folder = new Dir('example');
|
|
29
|
-
* // folder.path = '
|
|
32
|
+
* // folder.path = '/absolute/path/to/example'
|
|
30
33
|
* const child = folder.dir('path/to/dir');
|
|
31
|
-
* // child.path = '
|
|
34
|
+
* // child.path = '/absolute/path/to/example/path/to/dir'
|
|
32
35
|
*/
|
|
33
36
|
dir(subPath: string) {
|
|
34
|
-
return new Dir(path.resolve(this.path, subPath));
|
|
37
|
+
return new Dir(path.resolve(this.path, this.notAbsolute(subPath)));
|
|
35
38
|
}
|
|
36
39
|
|
|
37
40
|
tempDir(subPath: string) {
|
|
38
|
-
return new TempDir(path.resolve(this.path, subPath));
|
|
41
|
+
return new TempDir(path.resolve(this.path, this.notAbsolute(subPath)));
|
|
39
42
|
}
|
|
40
43
|
|
|
41
|
-
sanitize(
|
|
42
|
-
|
|
44
|
+
sanitize(filename: string) {
|
|
45
|
+
const notUrl = filename.replace('https://', '').replace('www.', '');
|
|
46
|
+
return sanitizeFilename(notUrl, { replacement: '_' }).slice(-200);
|
|
43
47
|
}
|
|
44
48
|
|
|
45
49
|
/**
|
|
46
|
-
* @param base - The file name
|
|
50
|
+
* @param base - The file base (name and extension)
|
|
47
51
|
* @example
|
|
48
52
|
* const folder = new Dir('example');
|
|
49
53
|
* const filepath = folder.resolve('file.json');
|
|
@@ -56,19 +60,33 @@ export class Dir {
|
|
|
56
60
|
file(base: string) {
|
|
57
61
|
return new File(this.filepath(base));
|
|
58
62
|
}
|
|
63
|
+
|
|
64
|
+
get files() {
|
|
65
|
+
return fs.readdirSync(this.path).map((filename) => this.file(filename));
|
|
66
|
+
}
|
|
59
67
|
}
|
|
60
68
|
|
|
61
69
|
/**
|
|
62
|
-
* Extends Dir class with method to `clear()` contents
|
|
70
|
+
* Extends Dir class with method to `clear()` contents.
|
|
71
|
+
* Default path: `./.${Date.now()}`
|
|
63
72
|
*/
|
|
64
73
|
export class TempDir extends Dir {
|
|
74
|
+
constructor(inputPath = `./.${Date.now()}`) {
|
|
75
|
+
super(inputPath);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* > ⚠️ Warning! This deletes the directory, make sure it's not
|
|
80
|
+
*/
|
|
65
81
|
clear() {
|
|
66
82
|
fs.rmSync(this.path, { recursive: true, force: true });
|
|
67
|
-
this.
|
|
83
|
+
fs.mkdirSync(this.path, { recursive: true });
|
|
68
84
|
}
|
|
69
85
|
}
|
|
70
86
|
|
|
71
87
|
/**
|
|
72
|
-
*
|
|
88
|
+
* Creates a '.temp' directory in current working directory
|
|
73
89
|
*/
|
|
74
|
-
export
|
|
90
|
+
export function temp() {
|
|
91
|
+
return new TempDir('.temp');
|
|
92
|
+
}
|
package/src/File.test.ts
CHANGED
package/src/File.ts
CHANGED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { describe } from 'node:test';
|
|
2
|
+
import assert from 'node:assert';
|
|
3
|
+
import { Format } from './Format.ts';
|
|
4
|
+
|
|
5
|
+
describe('Format.round', () => {
|
|
6
|
+
assert.equal(Format.round(1.22), '1');
|
|
7
|
+
assert.equal(Format.round(1.55), '2');
|
|
8
|
+
assert.equal(Format.round(1.823, 2), '1.82');
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
describe('Format.ms', () => {
|
|
12
|
+
const SECOND = 1000;
|
|
13
|
+
const MINUTE = 60 * SECOND;
|
|
14
|
+
const HOUR = 60 * MINUTE;
|
|
15
|
+
const DAY = 24 * HOUR;
|
|
16
|
+
assert.equal(Format.ms(100), '100ms');
|
|
17
|
+
assert.equal(Format.ms(5 * SECOND), '5s');
|
|
18
|
+
assert.equal(Format.ms(75 * SECOND), '1m 15s');
|
|
19
|
+
assert.equal(Format.ms(30 * MINUTE + 30 * SECOND), '30m 30s');
|
|
20
|
+
assert.equal(Format.ms(2 * HOUR + 2 * MINUTE), '2h 2m');
|
|
21
|
+
assert.equal(Format.ms(2 * DAY + 2 * HOUR), '2d 2h');
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
describe('Format.bytes', () => {
|
|
25
|
+
const base = 1024;
|
|
26
|
+
assert.equal(Format.bytes(2), '2 b');
|
|
27
|
+
assert.equal(Format.bytes(base), '1 KB');
|
|
28
|
+
assert.equal(Format.bytes(base + 0.1 * base), '1.1 KB');
|
|
29
|
+
assert.equal(Format.bytes(base + 0.25 * base), '1.25 KB');
|
|
30
|
+
assert.equal(Format.bytes(base ** 2), '1 MB');
|
|
31
|
+
assert.equal(Format.bytes(base ** 3), '1 GB');
|
|
32
|
+
assert.equal(Format.bytes(base ** 4), '1 TB');
|
|
33
|
+
assert.equal(Format.bytes(base ** 5), '1,024 TB');
|
|
34
|
+
});
|
package/src/Format.ts
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { format, formatISO, type DateArg } from 'date-fns';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Helpers for formatting dates, times, and numbers as strings
|
|
5
|
+
*/
|
|
6
|
+
export class Format {
|
|
7
|
+
/**
|
|
8
|
+
* date-fns format() with some shortcuts
|
|
9
|
+
* @param formatStr
|
|
10
|
+
* 'iso' to get ISO date, 'ymd' to format as 'yyyy-MM-dd', full options: https://date-fns.org/v4.1.0/docs/format
|
|
11
|
+
*/
|
|
12
|
+
static date(formatStr: 'iso' | 'ymd' | string = 'iso', d: DateArg<Date> = new Date()) {
|
|
13
|
+
if (formatStr === 'iso') return formatISO(d);
|
|
14
|
+
if (formatStr === 'ymd') return format(d, 'yyyy-MM-dd');
|
|
15
|
+
return format(d, formatStr);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Round a number to a specific set of places
|
|
20
|
+
*/
|
|
21
|
+
static round(n: number, places = 0) {
|
|
22
|
+
return new Intl.NumberFormat('en-US', { maximumFractionDigits: places }).format(n);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Make millisecond durations actually readable (eg "123ms", "3.56s", "1m 34s", "3h 24m", "2d 4h")
|
|
27
|
+
*/
|
|
28
|
+
static ms(ms: number) {
|
|
29
|
+
if (ms < 1000) return `${this.round(ms)}ms`;
|
|
30
|
+
const s = ms / 1000;
|
|
31
|
+
if (s < 60) return `${this.round(s, 2)}s`;
|
|
32
|
+
const m = Math.floor(s / 60);
|
|
33
|
+
if (m < 60) return `${m}m ${Math.floor(s) % 60}s`;
|
|
34
|
+
const h = Math.floor(m / 60);
|
|
35
|
+
if (h < 24) return `${h}h ${m % 60}m`;
|
|
36
|
+
const d = Math.floor(h / 24);
|
|
37
|
+
return `${d}d ${h % 24}h`;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
static bytes(b: number) {
|
|
41
|
+
const labels = ['b', 'KB', 'MB', 'GB', 'TB'];
|
|
42
|
+
let factor = 0;
|
|
43
|
+
while (b >= 1024 && labels[factor + 1]) {
|
|
44
|
+
b = b / 1024;
|
|
45
|
+
factor++;
|
|
46
|
+
}
|
|
47
|
+
return `${this.round(b, 2)} ${labels[factor]}`;
|
|
48
|
+
}
|
|
49
|
+
}
|
package/src/Log.ts
CHANGED
|
@@ -25,9 +25,9 @@ export class Log {
|
|
|
25
25
|
*/
|
|
26
26
|
static #toGcloud(entry: Entry) {
|
|
27
27
|
if (entry.details?.length === 1) {
|
|
28
|
-
console.log(JSON.stringify({ ...entry, details: entry.details[0] }));
|
|
28
|
+
console.log(JSON.stringify(snapshot({ ...entry, details: entry.details[0] })));
|
|
29
29
|
} else {
|
|
30
|
-
console.log(JSON.stringify(entry));
|
|
30
|
+
console.log(JSON.stringify(snapshot(entry)));
|
|
31
31
|
}
|
|
32
32
|
}
|
|
33
33
|
|
|
@@ -58,11 +58,12 @@ export class Log {
|
|
|
58
58
|
|
|
59
59
|
/**
|
|
60
60
|
* Handle first argument being a string or an object with a 'message' prop
|
|
61
|
-
* Also snapshots special objects (eg Error, Response) to keep props in later JSON.stringify output
|
|
62
61
|
*/
|
|
63
62
|
static prepare(...input: unknown[]): { message?: string; details: unknown[] } {
|
|
64
|
-
let [first, ...rest] = input
|
|
65
|
-
if (typeof first === 'string')
|
|
63
|
+
let [first, ...rest] = input;
|
|
64
|
+
if (typeof first === 'string') {
|
|
65
|
+
return { message: first, details: rest };
|
|
66
|
+
}
|
|
66
67
|
// @ts-ignore
|
|
67
68
|
if (isObjectLike(first) && typeof first['message'] === 'string') {
|
|
68
69
|
const { message, ...firstDetails } = first as { message: string };
|
package/src/index.ts
CHANGED
|
@@ -2,6 +2,7 @@ export { Dir, TempDir, temp } from './Dir.ts';
|
|
|
2
2
|
export { Cache } from './Cache.ts';
|
|
3
3
|
export { Fetcher, type Route, type Query, type FetchOptions } from './Fetcher.ts';
|
|
4
4
|
export { File, FileType, FileTypeJson, FileTypeNdjson, FileTypeCsv } from './File.ts';
|
|
5
|
+
export { Format } from './Format.ts';
|
|
5
6
|
export { Log } from './Log.ts';
|
|
6
7
|
export { snapshot } from './snapshot.ts';
|
|
7
8
|
export { timeout } from './timeout.ts';
|
package/src/snapshot.test.ts
CHANGED
|
@@ -46,9 +46,9 @@ describe('snapshot', () => {
|
|
|
46
46
|
const t1 = createThing(1);
|
|
47
47
|
const t2 = createThing(2, t1);
|
|
48
48
|
const result = snapshot(t1, 20) as Thing;
|
|
49
|
-
const f1 = temp.file('recursive').json(result);
|
|
49
|
+
const f1 = temp().file('recursive').json(result);
|
|
50
50
|
const parsed = f1.read();
|
|
51
|
-
const f2 = temp.file('recursive2').json(parsed);
|
|
51
|
+
const f2 = temp().file('recursive2').json(parsed);
|
|
52
52
|
assert.deepEqual(f1.read(), f2.read());
|
|
53
53
|
});
|
|
54
54
|
});
|