@brianbuie/node-kit 0.11.0 → 0.12.0

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 CHANGED
@@ -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), [Variables](#variables)
22
22
 
23
23
  # Classes
24
24
 
@@ -37,7 +37,7 @@ Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types
37
37
  | [TempDir](#class-tempdir) |
38
38
  | [TypeWriter](#class-typewriter) |
39
39
 
40
- Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types)
40
+ Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types), [Variables](#variables)
41
41
 
42
42
  ---
43
43
 
@@ -60,18 +60,22 @@ export class Cache<T> {
60
60
  }
61
61
  ```
62
62
 
63
- Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types)
63
+ Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types), [Variables](#variables)
64
64
 
65
65
  ---
66
66
  ## Class: Dir
67
67
 
68
68
  Reference to a specific directory with methods to create and list files.
69
- Created immediately if it doesn't exist
69
+ Default path: './'
70
+ > Created on file system the first time .path is read or any methods are used
70
71
 
71
72
  ```ts
72
73
  export class Dir {
73
- path;
74
+ #inputPath;
75
+ #resolved?: string;
74
76
  constructor(inputPath = "./")
77
+ get path()
78
+ notAbsolute(subPath: string)
75
79
  dir(subPath: string)
76
80
  tempDir(subPath: string)
77
81
  sanitize(filename: string)
@@ -107,7 +111,7 @@ dir(subPath: string)
107
111
  Argument Details
108
112
 
109
113
  + **subPath**
110
- + relative path to create
114
+ + relative path to create (not absolute)
111
115
 
112
116
  Example
113
117
 
@@ -127,7 +131,7 @@ filepath(base: string)
127
131
  Argument Details
128
132
 
129
133
  + **base**
130
- + The file name with extension
134
+ + The file base (name and extension)
131
135
 
132
136
  Example
133
137
 
@@ -137,9 +141,22 @@ const filepath = folder.resolve('file.json');
137
141
  // 'example/file.json'
138
142
  ```
139
143
 
144
+ ### Method tempDir
145
+
146
+ Creates a new TempDir inside current Dir
147
+
148
+ ```ts
149
+ tempDir(subPath: string)
150
+ ```
151
+
152
+ Argument Details
153
+
154
+ + **subPath**
155
+ + relative path to create (not absolute)
156
+
140
157
  </details>
141
158
 
142
- Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types)
159
+ Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types), [Variables](#variables)
143
160
 
144
161
  ---
145
162
  ## Class: Fetcher
@@ -237,12 +254,12 @@ See also: [FetchOptions](#type-fetchoptions), [Route](#type-route)
237
254
 
238
255
  </details>
239
256
 
240
- Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types)
257
+ Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types), [Variables](#variables)
241
258
 
242
259
  ---
243
260
  ## Class: File
244
261
 
245
- WARNING: API will change!
262
+ > ⚠️ WARNING: API will change!
246
263
 
247
264
  ```ts
248
265
  export class File {
@@ -298,7 +315,7 @@ lines as strings, removes trailing '\n'
298
315
 
299
316
  </details>
300
317
 
301
- Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types)
318
+ Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types), [Variables](#variables)
302
319
 
303
320
  ---
304
321
  ## Class: FileType
@@ -315,7 +332,7 @@ export class FileType {
315
332
  }
316
333
  ```
317
334
 
318
- Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types)
335
+ Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types), [Variables](#variables)
319
336
 
320
337
  ---
321
338
  ## Class: FileTypeCsv
@@ -334,7 +351,7 @@ export class FileTypeCsv<Row extends object> extends FileType {
334
351
 
335
352
  See also: [FileType](#class-filetype)
336
353
 
337
- Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types)
354
+ Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types), [Variables](#variables)
338
355
 
339
356
  ---
340
357
  ## Class: FileTypeJson
@@ -352,7 +369,7 @@ export class FileTypeJson<T> extends FileType {
352
369
 
353
370
  See also: [FileType](#class-filetype)
354
371
 
355
- Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types)
372
+ Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types), [Variables](#variables)
356
373
 
357
374
  ---
358
375
  ## Class: FileTypeNdjson
@@ -369,7 +386,7 @@ export class FileTypeNdjson<T extends object> extends FileType {
369
386
 
370
387
  See also: [FileType](#class-filetype)
371
388
 
372
- Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types)
389
+ Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types), [Variables](#variables)
373
390
 
374
391
  ---
375
392
  ## Class: Format
@@ -420,7 +437,7 @@ static round(n: number, places = 0)
420
437
 
421
438
  </details>
422
439
 
423
- Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types)
440
+ Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types), [Variables](#variables)
424
441
 
425
442
  ---
426
443
  ## Class: Log
@@ -474,7 +491,6 @@ static error(...input: unknown[])
474
491
  ### Method prepare
475
492
 
476
493
  Handle first argument being a string or an object with a 'message' prop
477
- Also snapshots special objects (eg Error, Response) to keep props in later JSON.stringify output
478
494
 
479
495
  ```ts
480
496
  static prepare(...input: unknown[]): {
@@ -485,22 +501,38 @@ static prepare(...input: unknown[]): {
485
501
 
486
502
  </details>
487
503
 
488
- Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types)
504
+ Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types), [Variables](#variables)
489
505
 
490
506
  ---
491
507
  ## Class: TempDir
492
508
 
493
- Extends Dir class with method to `clear()` contents
509
+ Extends Dir class with method to `clear()` contents.
510
+ Default path: `./.temp`
494
511
 
495
512
  ```ts
496
513
  export class TempDir extends Dir {
514
+ constructor(inputPath = `./.temp`)
497
515
  clear()
498
516
  }
499
517
  ```
500
518
 
501
- See also: [Dir](#class-dir)
519
+ See also: [Dir](#class-dir), [temp](#variable-temp)
520
+
521
+ <details>
522
+
523
+ <summary>Class TempDir Details</summary>
524
+
525
+ ### Method clear
526
+
527
+ > ⚠️ Warning! This deletes the directory!
528
+
529
+ ```ts
530
+ clear()
531
+ ```
532
+
533
+ </details>
502
534
 
503
- Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types)
535
+ Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types), [Variables](#variables)
504
536
 
505
537
  ---
506
538
  ## Class: TypeWriter
@@ -534,7 +566,7 @@ async toString()
534
566
 
535
567
  </details>
536
568
 
537
- Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types)
569
+ Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types), [Variables](#variables)
538
570
 
539
571
  ---
540
572
  # Functions
@@ -542,10 +574,9 @@ Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types
542
574
  | |
543
575
  | --- |
544
576
  | [snapshot](#function-snapshot) |
545
- | [temp](#function-temp) |
546
577
  | [timeout](#function-timeout) |
547
578
 
548
- Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types)
579
+ Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types), [Variables](#variables)
549
580
 
550
581
  ---
551
582
 
@@ -558,18 +589,7 @@ functions are removed
558
589
  export function snapshot(i: unknown, max = 50, depth = 0): any
559
590
  ```
560
591
 
561
- Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types)
562
-
563
- ---
564
- ## Function: temp
565
-
566
- Creates a '.temp' directory in current working directory
567
-
568
- ```ts
569
- export function temp()
570
- ```
571
-
572
- Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types)
592
+ Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types), [Variables](#variables)
573
593
 
574
594
  ---
575
595
  ## Function: timeout
@@ -578,7 +598,7 @@ Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types
578
598
  export async function timeout(ms: number)
579
599
  ```
580
600
 
581
- Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types)
601
+ Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types), [Variables](#variables)
582
602
 
583
603
  ---
584
604
  # Types
@@ -589,7 +609,7 @@ Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types
589
609
  | [Query](#type-query) |
590
610
  | [Route](#type-route) |
591
611
 
592
- Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types)
612
+ Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types), [Variables](#variables)
593
613
 
594
614
  ---
595
615
 
@@ -609,7 +629,7 @@ export type FetchOptions = RequestInit & {
609
629
 
610
630
  See also: [Query](#type-query), [timeout](#function-timeout)
611
631
 
612
- Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types)
632
+ Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types), [Variables](#variables)
613
633
 
614
634
  ---
615
635
  ## Type: Query
@@ -618,7 +638,7 @@ Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types
618
638
  export type Query = Record<string, QueryVal | QueryVal[]>
619
639
  ```
620
640
 
621
- Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types)
641
+ Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types), [Variables](#variables)
622
642
 
623
643
  ---
624
644
  ## Type: Route
@@ -627,7 +647,20 @@ Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types
627
647
  export type Route = string | URL
628
648
  ```
629
649
 
630
- Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types)
650
+ Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types), [Variables](#variables)
651
+
652
+ ---
653
+ # Variables
654
+
655
+ ## Variable: temp
656
+
657
+ ```ts
658
+ temp = new TempDir()
659
+ ```
660
+
661
+ See also: [TempDir](#class-tempdir)
662
+
663
+ Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types), [Variables](#variables)
631
664
 
632
665
  ---
633
666
 
package/dist/index.d.mts CHANGED
@@ -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;
@@ -91,17 +91,23 @@ declare class FileTypeCsv<Row extends object> extends FileType {
91
91
  //#region src/Dir.d.ts
92
92
  /**
93
93
  * Reference to a specific directory with methods to create and list files.
94
- * Created immediately if it doesn't exist
94
+ * Default path: './'
95
+ * > Created on file system the first time .path is read or any methods are used
95
96
  */
96
97
  declare class Dir {
97
- path: string;
98
+ #private;
98
99
  /**
99
100
  * @param path can be relative to workspace or absolute
100
101
  */
101
102
  constructor(inputPath?: string);
103
+ /**
104
+ * The path of this Dir instance. Created on file system the first time this property is read/used.
105
+ */
106
+ get path(): string;
107
+ notAbsolute(subPath: string): string;
102
108
  /**
103
109
  * Create a new Dir inside the current Dir
104
- * @param subPath relative path to create
110
+ * @param subPath relative path to create (not absolute)
105
111
  * @example
106
112
  * const folder = new Dir('example');
107
113
  * // folder.path = '/absolute/path/to/example'
@@ -109,10 +115,14 @@ declare class Dir {
109
115
  * // child.path = '/absolute/path/to/example/path/to/dir'
110
116
  */
111
117
  dir(subPath: string): Dir;
118
+ /**
119
+ * Creates a new TempDir inside current Dir
120
+ * @param subPath relative path to create (not absolute)
121
+ */
112
122
  tempDir(subPath: string): TempDir;
113
123
  sanitize(filename: string): string;
114
124
  /**
115
- * @param base - The file name with extension
125
+ * @param base - The file base (name and extension)
116
126
  * @example
117
127
  * const folder = new Dir('example');
118
128
  * const filepath = folder.resolve('file.json');
@@ -123,15 +133,20 @@ declare class Dir {
123
133
  get files(): File[];
124
134
  }
125
135
  /**
126
- * Extends Dir class with method to `clear()` contents
136
+ * Extends Dir class with method to `clear()` contents.
137
+ * Default path: `./.temp`
127
138
  */
128
139
  declare class TempDir extends Dir {
140
+ constructor(inputPath?: string);
141
+ /**
142
+ * > ⚠️ Warning! This deletes the directory!
143
+ */
129
144
  clear(): void;
130
145
  }
131
146
  /**
132
- * Creates a '.temp' directory in current working directory
147
+ * './.temp' in current working directory
133
148
  */
134
- declare function temp(): TempDir;
149
+ declare const temp: TempDir;
135
150
  //#endregion
136
151
  //#region src/Cache.d.ts
137
152
  /**
@@ -249,7 +264,6 @@ declare class Log {
249
264
  static isTest: boolean;
250
265
  /**
251
266
  * Handle first argument being a string or an object with a 'message' prop
252
- * Also snapshots special objects (eg Error, Response) to keep props in later JSON.stringify output
253
267
  */
254
268
  static prepare(...input: unknown[]): {
255
269
  message?: string;
@@ -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
@@ -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;
@@ -212,20 +212,35 @@ var FileTypeCsv = class extends FileType {
212
212
  //#region src/Dir.ts
213
213
  /**
214
214
  * Reference to a specific directory with methods to create and list files.
215
- * Created immediately if it doesn't exist
215
+ * Default path: './'
216
+ * > Created on file system the first time .path is read or any methods are used
216
217
  */
217
218
  var Dir = class Dir {
218
- path;
219
+ #inputPath;
220
+ #resolved;
219
221
  /**
220
222
  * @param path can be relative to workspace or absolute
221
223
  */
222
224
  constructor(inputPath = "./") {
223
- this.path = path.resolve(inputPath);
224
- fs.mkdirSync(this.path, { recursive: true });
225
+ this.#inputPath = path.resolve(inputPath);
226
+ }
227
+ /**
228
+ * The path of this Dir instance. Created on file system the first time this property is read/used.
229
+ */
230
+ get path() {
231
+ if (!this.#resolved) {
232
+ this.#resolved = path.resolve(this.#inputPath);
233
+ fs.mkdirSync(this.#resolved, { recursive: true });
234
+ }
235
+ return this.#resolved;
236
+ }
237
+ notAbsolute(subPath) {
238
+ if (path.isAbsolute(subPath)) throw new Error(`Absolute path provided: "${subPath}"`);
239
+ return subPath;
225
240
  }
226
241
  /**
227
242
  * Create a new Dir inside the current Dir
228
- * @param subPath relative path to create
243
+ * @param subPath relative path to create (not absolute)
229
244
  * @example
230
245
  * const folder = new Dir('example');
231
246
  * // folder.path = '/absolute/path/to/example'
@@ -233,16 +248,20 @@ var Dir = class Dir {
233
248
  * // child.path = '/absolute/path/to/example/path/to/dir'
234
249
  */
235
250
  dir(subPath) {
236
- return new Dir(path.resolve(this.path, subPath));
251
+ return new Dir(path.resolve(this.path, this.notAbsolute(subPath)));
237
252
  }
253
+ /**
254
+ * Creates a new TempDir inside current Dir
255
+ * @param subPath relative path to create (not absolute)
256
+ */
238
257
  tempDir(subPath) {
239
- return new TempDir(path.resolve(this.path, subPath));
258
+ return new TempDir(path.resolve(this.path, this.notAbsolute(subPath)));
240
259
  }
241
260
  sanitize(filename) {
242
261
  return sanitizeFilename(filename.replace("https://", "").replace("www.", ""), { replacement: "_" }).slice(-200);
243
262
  }
244
263
  /**
245
- * @param base - The file name with extension
264
+ * @param base - The file base (name and extension)
246
265
  * @example
247
266
  * const folder = new Dir('example');
248
267
  * const filepath = folder.resolve('file.json');
@@ -259,9 +278,16 @@ var Dir = class Dir {
259
278
  }
260
279
  };
261
280
  /**
262
- * Extends Dir class with method to `clear()` contents
281
+ * Extends Dir class with method to `clear()` contents.
282
+ * Default path: `./.temp`
263
283
  */
264
284
  var TempDir = class extends Dir {
285
+ constructor(inputPath = `./.temp`) {
286
+ super(inputPath);
287
+ }
288
+ /**
289
+ * > ⚠️ Warning! This deletes the directory!
290
+ */
265
291
  clear() {
266
292
  fs.rmSync(this.path, {
267
293
  recursive: true,
@@ -271,11 +297,9 @@ var TempDir = class extends Dir {
271
297
  }
272
298
  };
273
299
  /**
274
- * Creates a '.temp' directory in current working directory
300
+ * './.temp' in current working directory
275
301
  */
276
- function temp() {
277
- return new TempDir(".temp");
278
- }
302
+ const temp = new TempDir();
279
303
 
280
304
  //#endregion
281
305
  //#region src/Cache.ts
@@ -471,11 +495,11 @@ var Log = class {
471
495
  * Gcloud parses JSON in stdout
472
496
  */
473
497
  static #toGcloud(entry) {
474
- if (entry.details?.length === 1) console.log(JSON.stringify({
498
+ if (entry.details?.length === 1) console.log(JSON.stringify(snapshot({
475
499
  ...entry,
476
500
  details: entry.details[0]
477
- }));
478
- else console.log(JSON.stringify(entry));
501
+ })));
502
+ else console.log(JSON.stringify(snapshot(entry)));
479
503
  }
480
504
  /**
481
505
  * Includes colors and better inspection for logging during dev
@@ -518,10 +542,9 @@ var Log = class {
518
542
  }
519
543
  /**
520
544
  * Handle first argument being a string or an object with a 'message' prop
521
- * Also snapshots special objects (eg Error, Response) to keep props in later JSON.stringify output
522
545
  */
523
546
  static prepare(...input) {
524
- let [first, ...rest] = input.map((i) => snapshot(i));
547
+ let [first, ...rest] = input;
525
548
  if (typeof first === "string") return {
526
549
  message: first,
527
550
  details: rest
@@ -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/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 */\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 /**\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, subPath));\n }\n\n tempDir(subPath: string) {\n return new TempDir(path.resolve(this.path, subPath));\n }\n\n sanitize(filename: string) {\n return sanitizeFilename(filename.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 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 */\nexport class TempDir extends Dir {\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({ ...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","#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 { 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 * 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 = path.resolve(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 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 (not absolute)\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 /**\n * Creates a new TempDir inside current Dir\n * @param subPath relative path to create (not absolute)\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: `./.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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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brianbuie/node-kit",
3
- "version": "0.11.0",
3
+ "version": "0.12.0",
4
4
  "license": "ISC",
5
5
  "description": "Basic tools for Node.js projects",
6
6
  "author": "Brian Buie <brian@buie.dev>",
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,23 @@ describe('Dir', () => {
18
18
  assert(sub.path.includes(subPath));
19
19
  });
20
20
 
21
- it('TempDir.tempDir returns instance of TempDir', () => {
22
- const sub = temp().tempDir('example');
21
+ it('.tempDir returns instance of TempDir', () => {
22
+ const sub = testDir.tempDir('example');
23
23
  assert(sub instanceof TempDir);
24
24
  });
25
25
 
26
+ it('.dir() and .tempDir() throw on absolute path input', () => {
27
+ assert.throws(() => {
28
+ testDir.dir(testDir.path);
29
+ });
30
+ assert.throws(() => {
31
+ testDir.tempDir(testDir.path);
32
+ });
33
+ });
34
+
26
35
  it('Resolves filenames in folder', () => {
27
- const txt = temp().filepath('test.txt');
28
- assert(txt.includes(temp().path));
36
+ const txt = testDir.filepath('test.txt');
37
+ assert(txt.includes(testDir.path));
29
38
  assert(txt.includes('test.txt'));
30
39
  });
31
40
  });
package/src/Dir.ts CHANGED
@@ -5,22 +5,39 @@ import { File } from './File.ts';
5
5
 
6
6
  /**
7
7
  * Reference to a specific directory with methods to create and list files.
8
- * Created immediately if it doesn't exist
8
+ * Default path: './'
9
+ * > Created on file system the first time .path is read or any methods are used
9
10
  */
10
11
  export class Dir {
11
- path;
12
+ #inputPath;
13
+ #resolved?: string;
12
14
 
13
15
  /**
14
16
  * @param path can be relative to workspace or absolute
15
17
  */
16
18
  constructor(inputPath = './') {
17
- this.path = path.resolve(inputPath);
18
- fs.mkdirSync(this.path, { recursive: true });
19
+ this.#inputPath = path.resolve(inputPath);
20
+ }
21
+
22
+ /**
23
+ * The path of this Dir instance. Created on file system the first time this property is read/used.
24
+ */
25
+ get path() {
26
+ if (!this.#resolved) {
27
+ this.#resolved = path.resolve(this.#inputPath);
28
+ fs.mkdirSync(this.#resolved, { recursive: true });
29
+ }
30
+ return this.#resolved;
31
+ }
32
+
33
+ notAbsolute(subPath: string) {
34
+ if (path.isAbsolute(subPath)) throw new Error(`Absolute path provided: "${subPath}"`);
35
+ return subPath;
19
36
  }
20
37
 
21
38
  /**
22
39
  * Create a new Dir inside the current Dir
23
- * @param subPath relative path to create
40
+ * @param subPath relative path to create (not absolute)
24
41
  * @example
25
42
  * const folder = new Dir('example');
26
43
  * // folder.path = '/absolute/path/to/example'
@@ -28,19 +45,24 @@ export class Dir {
28
45
  * // child.path = '/absolute/path/to/example/path/to/dir'
29
46
  */
30
47
  dir(subPath: string) {
31
- return new Dir(path.resolve(this.path, subPath));
48
+ return new Dir(path.resolve(this.path, this.notAbsolute(subPath)));
32
49
  }
33
50
 
51
+ /**
52
+ * Creates a new TempDir inside current Dir
53
+ * @param subPath relative path to create (not absolute)
54
+ */
34
55
  tempDir(subPath: string) {
35
- return new TempDir(path.resolve(this.path, subPath));
56
+ return new TempDir(path.resolve(this.path, this.notAbsolute(subPath)));
36
57
  }
37
58
 
38
59
  sanitize(filename: string) {
39
- return sanitizeFilename(filename.replace('https://', '').replace('www.', ''), { replacement: '_' }).slice(-200);
60
+ const notUrl = filename.replace('https://', '').replace('www.', '');
61
+ return sanitizeFilename(notUrl, { replacement: '_' }).slice(-200);
40
62
  }
41
63
 
42
64
  /**
43
- * @param base - The file name with extension
65
+ * @param base - The file base (name and extension)
44
66
  * @example
45
67
  * const folder = new Dir('example');
46
68
  * const filepath = folder.resolve('file.json');
@@ -60,9 +82,17 @@ export class Dir {
60
82
  }
61
83
 
62
84
  /**
63
- * Extends Dir class with method to `clear()` contents
85
+ * Extends Dir class with method to `clear()` contents.
86
+ * Default path: `./.temp`
64
87
  */
65
88
  export class TempDir extends Dir {
89
+ constructor(inputPath = `./.temp`) {
90
+ super(inputPath);
91
+ }
92
+
93
+ /**
94
+ * > ⚠️ Warning! This deletes the directory!
95
+ */
66
96
  clear() {
67
97
  fs.rmSync(this.path, { recursive: true, force: true });
68
98
  fs.mkdirSync(this.path, { recursive: true });
@@ -70,8 +100,6 @@ export class TempDir extends Dir {
70
100
  }
71
101
 
72
102
  /**
73
- * Creates a '.temp' directory in current working directory
103
+ * './.temp' in current working directory
74
104
  */
75
- export function temp() {
76
- return new TempDir('.temp');
77
- }
105
+ export const temp = new TempDir();
package/src/File.test.ts CHANGED
@@ -3,7 +3,7 @@ import assert from 'node:assert';
3
3
  import { temp } from './Dir.ts';
4
4
  import { File } from './File.ts';
5
5
 
6
- const testDir = temp().tempDir('file-test');
6
+ const testDir = temp.tempDir('file-test');
7
7
  testDir.clear();
8
8
 
9
9
  const thing = {
package/src/File.ts CHANGED
@@ -6,7 +6,7 @@ import { writeToStream, parseStream } from 'fast-csv';
6
6
  import { snapshot } from './snapshot.ts';
7
7
 
8
8
  /**
9
- * WARNING: API will change!
9
+ * > ⚠️ WARNING: API will change!
10
10
  */
11
11
  export class File {
12
12
  path;
@@ -1,34 +1,36 @@
1
- import { describe } from 'node:test';
1
+ import { describe, it } from 'node:test';
2
2
  import assert from 'node:assert';
3
3
  import { Format } from './Format.ts';
4
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
- });
5
+ describe('Format', () => {
6
+ it('round', () => {
7
+ assert.equal(Format.round(1.22), '1');
8
+ assert.equal(Format.round(1.55), '2');
9
+ assert.equal(Format.round(1.823, 2), '1.82');
10
+ });
10
11
 
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
- });
12
+ it('ms', () => {
13
+ const SECOND = 1000;
14
+ const MINUTE = 60 * SECOND;
15
+ const HOUR = 60 * MINUTE;
16
+ const DAY = 24 * HOUR;
17
+ assert.equal(Format.ms(100), '100ms');
18
+ assert.equal(Format.ms(5 * SECOND), '5s');
19
+ assert.equal(Format.ms(75 * SECOND), '1m 15s');
20
+ assert.equal(Format.ms(30 * MINUTE + 30 * SECOND), '30m 30s');
21
+ assert.equal(Format.ms(2 * HOUR + 2 * MINUTE), '2h 2m');
22
+ assert.equal(Format.ms(2 * DAY + 2 * HOUR), '2d 2h');
23
+ });
23
24
 
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');
25
+ it('bytes', () => {
26
+ const base = 1024;
27
+ assert.equal(Format.bytes(2), '2 b');
28
+ assert.equal(Format.bytes(base), '1 KB');
29
+ assert.equal(Format.bytes(base + 0.1 * base), '1.1 KB');
30
+ assert.equal(Format.bytes(base + 0.25 * base), '1.25 KB');
31
+ assert.equal(Format.bytes(base ** 2), '1 MB');
32
+ assert.equal(Format.bytes(base ** 3), '1 GB');
33
+ assert.equal(Format.bytes(base ** 4), '1 TB');
34
+ assert.equal(Format.bytes(base ** 5), '1,024 TB');
35
+ });
34
36
  });
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.map((i) => snapshot(i));
65
- if (typeof first === 'string') return { message: first, details: rest };
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 };
@@ -3,6 +3,9 @@ import assert from 'node:assert';
3
3
  import { snapshot } from './snapshot.ts';
4
4
  import { temp } from './Dir.ts';
5
5
 
6
+ const testDir = temp.tempDir('snapshot');
7
+ testDir.clear();
8
+
6
9
  describe('snapshot', () => {
7
10
  it('Captures Error details', () => {
8
11
  try {
@@ -46,9 +49,9 @@ describe('snapshot', () => {
46
49
  const t1 = createThing(1);
47
50
  const t2 = createThing(2, t1);
48
51
  const result = snapshot(t1, 20) as Thing;
49
- const f1 = temp().file('recursive').json(result);
52
+ const f1 = testDir.file('recursive').json(result);
50
53
  const parsed = f1.read();
51
- const f2 = temp().file('recursive2').json(parsed);
54
+ const f2 = testDir.file('recursive2').json(parsed);
52
55
  assert.deepEqual(f1.read(), f2.read());
53
56
  });
54
57
  });