@brianbuie/node-kit 0.13.0 → 0.14.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
@@ -1,16 +1,16 @@
1
- [![NPM Version](https://img.shields.io/npm/v/%40brianbuie%2Fnode-kit)](https://www.npmjs.com/package/@brianbuie/node-kit)
2
-
3
1
  # Node Kit
4
2
 
5
- Basic tools for Node.js projects
3
+ Basic tools for quick node.js projects
6
4
 
7
5
  # Installing
8
6
 
7
+ [![NPM Version](https://img.shields.io/npm/v/%40brianbuie%2Fnode-kit)](https://www.npmjs.com/package/@brianbuie/node-kit)
8
+
9
9
  ```
10
10
  npm add @brianbuie/node-kit
11
11
  ```
12
12
 
13
- ```js
13
+ ```ts
14
14
  import { Fetcher, Log } from '@brianbuie/node-kit';
15
15
  ```
16
16
 
@@ -24,16 +24,16 @@ import { Fetcher, Log } from '@brianbuie/node-kit';
24
24
  }
25
25
  ```
26
26
 
27
- ### prettier.config.ts
27
+ ### prettier.config.js
28
28
 
29
- ```ts
30
- export * from './node_modules/@brianbuie/node-kit/prettier.config.ts';
29
+ ```js
30
+ export * from './node_modules/@brianbuie/node-kit/prettier.config.js';
31
31
  ```
32
32
 
33
33
  Or make changes:
34
34
 
35
- ```ts
36
- import baseConfig from './node_modules/@brianbuie/node-kit/prettier.config.ts';
35
+ ```js
36
+ import baseConfig from './node_modules/@brianbuie/node-kit/prettier.config.js';
37
37
 
38
38
  const config = {
39
39
  ...baseConfig,
@@ -101,18 +101,28 @@ export class Dir {
101
101
  #resolved?: string;
102
102
  isTemp;
103
103
  constructor(inputPath: string, options: DirOptions = {})
104
+ get pathUnsafe()
104
105
  get path()
106
+ get name()
105
107
  dir(subPath: string, options: DirOptions = { temp: this.isTemp })
106
108
  tempDir(subPath: string)
107
109
  sanitize(filename: string)
108
110
  filepath(base: string)
109
111
  file(base: string)
112
+ get contents(): (Dir | File)[]
113
+ get dirs()
110
114
  get files()
115
+ get videos()
116
+ get images()
117
+ get jsonFiles()
118
+ get ndjsonFiles()
119
+ get csvFiles()
120
+ get textFiles()
111
121
  clear()
112
122
  }
113
123
  ```
114
124
 
115
- See also: [DirOptions](#type-diroptions), [temp](#variable-temp)
125
+ See also: [DirOptions](#type-diroptions), [File](#class-file), [temp](#variable-temp)
116
126
 
117
127
  <details>
118
128
 
@@ -130,6 +140,14 @@ Argument Details
130
140
  + **path**
131
141
  + can be relative to workspace or absolute
132
142
 
143
+ ### Method clear
144
+
145
+ Deletes the contents of the directory. Only allowed if created with `temp` option set to `true` (or created with `dir.tempDir` method).
146
+
147
+ ```ts
148
+ clear()
149
+ ```
150
+
133
151
  ### Method dir
134
152
 
135
153
  Create a new Dir inside the current Dir
@@ -155,6 +173,14 @@ const child = folder.dir('path/to/dir');
155
173
  // child.path = '/path/to/cwd/example/path/to/dir'
156
174
  ```
157
175
 
176
+ ### Method file
177
+
178
+ Create a new file in this directory
179
+
180
+ ```ts
181
+ file(base: string)
182
+ ```
183
+
158
184
  ### Method filepath
159
185
 
160
186
  ```ts
@@ -853,3 +879,28 @@ Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types
853
879
  ---
854
880
 
855
881
  <!--#endregion ts2md-api-merged-here-->
882
+
883
+ # Development
884
+
885
+ Typecheck and run all tests from `*.test.ts` files
886
+
887
+ ```
888
+ pnpm test
889
+ ```
890
+
891
+ Format with Prettier, generate API docs for this Readme
892
+
893
+ ```
894
+ pnpm build
895
+ ```
896
+
897
+ Release a new version
898
+
899
+ - runs test and build
900
+ - If no unstaged changes, creates a new commit with version tag (`preversion` script in package.json)
901
+ - Pushes to github (`postversion` script in package.json)
902
+ - Triggers github workflow that publishes to npm
903
+
904
+ ```
905
+ npm version [patch|minor|major]
906
+ ```
package/dist/index.d.mts CHANGED
@@ -158,10 +158,22 @@ declare class Dir {
158
158
  * @param path can be relative to workspace or absolute
159
159
  */
160
160
  constructor(inputPath: string, options?: DirOptions);
161
+ /**
162
+ * The path of the directory, which might not exist yet.
163
+ */
164
+ get pathUnsafe(): string;
161
165
  /**
162
166
  * The path of this Dir instance. Created on file system the first time this property is read/used.
167
+ * Safe to use the directory immediately, without calling mkdir separately.
163
168
  */
164
169
  get path(): string;
170
+ /**
171
+ * The last segment in the path. Doesn't read this.path, to avoid creating directory on file system before it's needed.
172
+ * @example
173
+ * const example = new Dir('/path/to/folder');
174
+ * console.log(example.name); // "folder"
175
+ */
176
+ get name(): string;
165
177
  /**
166
178
  * Create a new Dir inside the current Dir
167
179
  * @param subPath
@@ -189,8 +201,61 @@ declare class Dir {
189
201
  * // 'example/file.json'
190
202
  */
191
203
  filepath(base: string): string;
204
+ /**
205
+ * Create a new file in this directory
206
+ */
192
207
  file(base: string): File;
208
+ /**
209
+ * All files and subdirectories in in this directory, returned as Dir and File instances
210
+ */
211
+ get contents(): (Dir | File)[];
212
+ /**
213
+ * All subdirectories in this directory
214
+ */
215
+ get dirs(): Dir[];
216
+ /**
217
+ * All files in this directory
218
+ */
193
219
  get files(): File[];
220
+ /**
221
+ * All files with MIME type that includes "video"
222
+ */
223
+ get videos(): File[];
224
+ /**
225
+ * All files with MIME type that includes "image"
226
+ */
227
+ get images(): File[];
228
+ /**
229
+ * All files with ext ".json"
230
+ * @example
231
+ * // Directory of json files with the same shape
232
+ * const dataFiles = dataDir.jsonFiles.map(f => f.json<ExampleType>());
233
+ * // dataFiles: FileTypeJson<ExampleType>[]
234
+ */
235
+ get jsonFiles(): File[];
236
+ /**
237
+ * All files with ext ".ndjson"
238
+ * @example
239
+ * // Directory of ndjson files with the same shape
240
+ * const dataFiles = dataDir.ndjsonFiles.map(f => f.ndjson<ExampleType>());
241
+ * // dataFiles: FileTypeNdjson<ExampleType>[]
242
+ */
243
+ get ndjsonFiles(): File[];
244
+ /**
245
+ * All files with ext ".csv"
246
+ * @example
247
+ * // Directory of csv files with the same shape
248
+ * const dataFiles = dataDir.csvFile.map(f => f.csv<ExampleType>());
249
+ * // dataFiles: FileTypeCsv<ExampleType>[]
250
+ */
251
+ get csvFiles(): File[];
252
+ /**
253
+ * All files with ext ".txt"
254
+ */
255
+ get textFiles(): File[];
256
+ /**
257
+ * Deletes the contents of the directory. Only allowed if created with `temp` option set to `true` (or created with `dir.tempDir` method).
258
+ */
194
259
  clear(): void;
195
260
  }
196
261
  /**
@@ -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
@@ -291,7 +291,7 @@ var FileTypeCsv = class extends FileType {
291
291
  * @param options
292
292
  * include `{ temp: true }` to enable the `.clear()` method
293
293
  */
294
- var Dir = class {
294
+ var Dir = class Dir {
295
295
  #inputPath;
296
296
  #resolved;
297
297
  isTemp;
@@ -303,16 +303,32 @@ var Dir = class {
303
303
  this.isTemp = Boolean(options.temp);
304
304
  }
305
305
  /**
306
+ * The path of the directory, which might not exist yet.
307
+ */
308
+ get pathUnsafe() {
309
+ return this.#resolved || path.resolve(this.#inputPath);
310
+ }
311
+ /**
306
312
  * The path of this Dir instance. Created on file system the first time this property is read/used.
313
+ * Safe to use the directory immediately, without calling mkdir separately.
307
314
  */
308
315
  get path() {
309
316
  if (!this.#resolved) {
310
- this.#resolved = path.resolve(this.#inputPath);
317
+ this.#resolved = this.pathUnsafe;
311
318
  fs.mkdirSync(this.#resolved, { recursive: true });
312
319
  }
313
320
  return this.#resolved;
314
321
  }
315
322
  /**
323
+ * The last segment in the path. Doesn't read this.path, to avoid creating directory on file system before it's needed.
324
+ * @example
325
+ * const example = new Dir('/path/to/folder');
326
+ * console.log(example.name); // "folder"
327
+ */
328
+ get name() {
329
+ return this.pathUnsafe.split(path.sep).at(-1);
330
+ }
331
+ /**
316
332
  * Create a new Dir inside the current Dir
317
333
  * @param subPath
318
334
  * joined with parent Dir's path to make new Dir
@@ -347,12 +363,81 @@ var Dir = class {
347
363
  filepath(base) {
348
364
  return path.resolve(this.path, this.sanitize(base));
349
365
  }
366
+ /**
367
+ * Create a new file in this directory
368
+ */
350
369
  file(base) {
351
370
  return new File(this.filepath(base));
352
371
  }
372
+ /**
373
+ * All files and subdirectories in in this directory, returned as Dir and File instances
374
+ */
375
+ get contents() {
376
+ return fs.readdirSync(this.path).map((name) => fs.statSync(path.join(this.path, name)).isDirectory() ? this.dir(name) : this.file(name));
377
+ }
378
+ /**
379
+ * All subdirectories in this directory
380
+ */
381
+ get dirs() {
382
+ return this.contents.filter((f) => f instanceof Dir);
383
+ }
384
+ /**
385
+ * All files in this directory
386
+ */
353
387
  get files() {
354
- return fs.readdirSync(this.path).map((filename) => this.file(filename));
388
+ return this.contents.filter((f) => f instanceof File);
389
+ }
390
+ /**
391
+ * All files with MIME type that includes "video"
392
+ */
393
+ get videos() {
394
+ return this.files.filter((f) => f.type?.includes("video"));
355
395
  }
396
+ /**
397
+ * All files with MIME type that includes "image"
398
+ */
399
+ get images() {
400
+ return this.files.filter((f) => f.type?.includes("image"));
401
+ }
402
+ /**
403
+ * All files with ext ".json"
404
+ * @example
405
+ * // Directory of json files with the same shape
406
+ * const dataFiles = dataDir.jsonFiles.map(f => f.json<ExampleType>());
407
+ * // dataFiles: FileTypeJson<ExampleType>[]
408
+ */
409
+ get jsonFiles() {
410
+ return this.files.filter((f) => f.ext === ".json");
411
+ }
412
+ /**
413
+ * All files with ext ".ndjson"
414
+ * @example
415
+ * // Directory of ndjson files with the same shape
416
+ * const dataFiles = dataDir.ndjsonFiles.map(f => f.ndjson<ExampleType>());
417
+ * // dataFiles: FileTypeNdjson<ExampleType>[]
418
+ */
419
+ get ndjsonFiles() {
420
+ return this.files.filter((f) => f.ext === ".ndjson");
421
+ }
422
+ /**
423
+ * All files with ext ".csv"
424
+ * @example
425
+ * // Directory of csv files with the same shape
426
+ * const dataFiles = dataDir.csvFile.map(f => f.csv<ExampleType>());
427
+ * // dataFiles: FileTypeCsv<ExampleType>[]
428
+ */
429
+ get csvFiles() {
430
+ return this.files.filter((f) => f.ext === ".csv");
431
+ }
432
+ /**
433
+ * All files with ext ".txt"
434
+ */
435
+ get textFiles() {
436
+ return this.files.filter((f) => f.ext === ".txt");
437
+ }
438
+ /**
439
+ * Deletes the contents of the directory. Only allowed if created with `temp` option set to `true` (or created with `dir.tempDir` method).
440
+ */
356
441
  clear() {
357
442
  if (!this.isTemp) throw new Error("Dir is not temporary");
358
443
  fs.rmSync(this.path, {
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["output: Record<string, any>","obj: Record<string, any>","parsed: Row[]","#parseVal","#inputPath","#resolved","params: [string, string][]","timeout","#toGcloud","#toConsole","#log","entry: Entry"],"sources":["../src/snapshot.ts","../src/File.ts","../src/Dir.ts","../src/Cache.ts","../src/Fetcher.ts","../src/Format.ts","../src/Log.ts","../src/timeout.ts","../src/TypeWriter.ts"],"sourcesContent":["import { isObjectLike } from 'lodash-es';\n\n/**\n * Allows special objects (Error, Headers, Set) to be included in JSON.stringify output.\n * Functions are removed\n */\nexport function snapshot(i: unknown, max = 50, depth = 0): any {\n if (Array.isArray(i)) {\n if (depth === max) return [];\n return i.map(c => snapshot(c, max, depth + 1));\n }\n if (typeof i === 'function') return undefined;\n if (!isObjectLike(i)) return i;\n\n if (depth === max) return {};\n let output: Record<string, any> = {};\n // @ts-ignore If it has an 'entries' function, use that for looping (eg. Set, Map, Headers)\n if (typeof i.entries === 'function') {\n // @ts-ignore\n for (let [k, v] of i.entries()) {\n output[k] = snapshot(v, max, depth + 1);\n }\n return output;\n }\n\n // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Enumerability_and_ownership_of_properties\n\n // Get Enumerable, inherited properties\n const obj: Record<string, any> = i!;\n for (let key in obj) {\n output[key] = snapshot(obj[key], max, depth + 1);\n }\n\n // Get Non-enumberable, own properties\n Object.getOwnPropertyNames(obj).forEach(key => {\n output[key] = snapshot(obj[key], max, depth + 1);\n });\n\n return output;\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport { Readable } from 'node:stream';\nimport { finished } from 'node:stream/promises';\nimport mime from 'mime-types';\nimport { writeToStream, parseStream } from 'fast-csv';\nimport { snapshot } from './snapshot.ts';\n\n/**\n * Represents a file on the file system. If the file doesn't exist, it is created the first time it is written to.\n */\nexport class File {\n path;\n root;\n dir;\n base;\n name;\n ext;\n type;\n\n constructor(filepath: string) {\n this.path = path.resolve(filepath);\n const { root, dir, base, ext, name } = path.parse(this.path);\n this.root = root;\n this.dir = dir;\n this.base = base;\n this.name = name;\n this.ext = ext;\n this.type = mime.lookup(ext) || undefined;\n }\n\n get exists() {\n return fs.existsSync(this.path);\n }\n\n get stats(): Partial<fs.Stats> {\n return this.exists ? fs.statSync(this.path) : {};\n }\n\n /**\n * Deletes the file if it exists\n */\n delete() {\n fs.rmSync(this.path, { force: true });\n }\n\n /**\n * @returns the contents of the file as a string, or undefined if the file doesn't exist\n */\n read() {\n return this.exists ? fs.readFileSync(this.path, 'utf8') : undefined;\n }\n\n /**\n * @returns lines as strings, removes trailing '\\n'\n */\n lines() {\n const contents = (this.read() || '').split('\\n');\n return contents.at(-1)?.length ? contents : contents.slice(0, contents.length - 1);\n }\n\n get readStream() {\n return this.exists ? fs.createReadStream(this.path) : Readable.from([]);\n }\n\n get writeStream() {\n fs.mkdirSync(this.dir, { recursive: true });\n return fs.createWriteStream(this.path);\n }\n\n write(contents: string | ReadableStream) {\n fs.mkdirSync(this.dir, { recursive: true });\n if (typeof contents === 'string') return fs.writeFileSync(this.path, contents);\n if (contents instanceof ReadableStream) return finished(Readable.from(contents).pipe(this.writeStream));\n throw new Error(`Invalid content type: ${typeof contents}`);\n }\n\n /**\n * creates file if it doesn't exist, appends string or array of strings as new lines.\n * File always ends with '\\n', so contents don't need to be read before appending\n */\n append(lines: string | string[]) {\n if (!this.exists) this.write('');\n const contents = Array.isArray(lines) ? lines.join('\\n') : lines;\n fs.appendFileSync(this.path, contents + '\\n');\n }\n\n /**\n * @returns FileTypeJson adaptor for current File, adds '.json' extension if not present.\n * @example\n * const file = new File('./data').json({ key: 'val' }); // FileTypeJson<{ key: string; }>\n * console.log(file.path) // '/path/to/cwd/data.json'\n * file.write({ something: 'else' }) // ❌ property 'something' doesn't exist on type { key: string; }\n * @example\n * const file = new File('./data').json<object>({ key: 'val' }); // FileTypeJson<object>\n * file.write({ something: 'else' }) // ✅ data is typed as object\n */\n json<T>(contents?: T) {\n return new FileTypeJson<T>(this.path, contents);\n }\n\n /**\n * @example\n * const file = new File.json('data.json', { key: 'val' }); // FileTypeJson<{ key: string; }>\n */\n static get json() {\n return FileTypeJson;\n }\n\n /**\n * @returns FileTypeNdjson adaptor for current File, adds '.ndjson' extension if not present.\n */\n ndjson<T extends object>(lines?: T | T[]) {\n return new FileTypeNdjson<T>(this.path, lines);\n }\n /**\n * @example\n * const file = new File.ndjson('log', { key: 'val' }); // FileTypeNdjson<{ key: string; }>\n * console.log(file.path) // /path/to/cwd/log.ndjson\n */\n static get ndjson() {\n return FileTypeNdjson;\n }\n\n /**\n * @returns FileTypeCsv adaptor for current File, adds '.csv' extension if not present.\n * @example\n * const file = await new File('a').csv([{ col: 'val' }, { col: 'val2' }]); // FileTypeCsv<{ col: string; }>\n * await file.write([ { col2: 'val2' } ]); // ❌ 'col2' doesn't exist on type { col: string; }\n * await file.write({ col: 'val' }); // ✅ Writes one row\n * await file.write([{ col: 'val2' }, { col: 'val3' }]); // ✅ Writes multiple rows\n */\n async csv<T extends object>(rows?: T[], keys?: (keyof T)[]) {\n const csvFile = new FileTypeCsv<T>(this.path);\n if (rows) await csvFile.write(rows, keys);\n return csvFile;\n }\n\n static get csv() {\n return FileTypeCsv;\n }\n}\n\n/**\n * A generic file adaptor, extended by specific file type implementations\n */\nexport class FileType {\n file;\n\n constructor(filepath: string, contents?: string) {\n this.file = new File(filepath);\n if (contents) this.file.write(contents);\n }\n\n get path() {\n return this.file.path;\n }\n\n get root() {\n return this.file.root;\n }\n\n get dir() {\n return this.file.dir;\n }\n\n get base() {\n return this.file.base;\n }\n\n get name() {\n return this.file.name;\n }\n\n get ext() {\n return this.file.ext;\n }\n\n get type() {\n return this.file.type;\n }\n\n get exists() {\n return this.file.exists;\n }\n\n get stats() {\n return this.file.stats;\n }\n\n delete() {\n this.file.delete();\n }\n\n get readStream() {\n return this.file.readStream;\n }\n\n get writeStream() {\n return this.file.writeStream;\n }\n}\n\n/**\n * A .json file that maintains data type when reading/writing.\n * > ⚠️ This is mildly unsafe, important/foreign json files should be validated at runtime!\n * @example\n * const file = new FileTypeJson('./data', { key: 'val' }); // FileTypeJson<{ key: string; }>\n * console.log(file.path) // '/path/to/cwd/data.json'\n * file.write({ something: 'else' }) // ❌ property 'something' doesn't exist on type { key: string; }\n * @example\n * const file = new FileTypeJson<object>('./data', { key: 'val' }); // FileTypeJson<object>\n * file.write({ something: 'else' }) // ✅ data is typed as object\n */\nexport class FileTypeJson<T> extends FileType {\n constructor(filepath: string, contents?: T) {\n super(filepath.endsWith('.json') ? filepath : filepath + '.json');\n if (contents) this.write(contents);\n }\n\n read() {\n const contents = this.file.read();\n return contents ? (JSON.parse(contents) as T) : undefined;\n }\n\n write(contents: T) {\n this.file.write(JSON.stringify(snapshot(contents), null, 2));\n }\n}\n\n/**\n * New-line delimited json file (.ndjson)\n * @see https://jsonltools.com/ndjson-format-specification\n */\nexport class FileTypeNdjson<T extends object> extends FileType {\n constructor(filepath: string, lines?: T | T[]) {\n super(filepath.endsWith('.ndjson') ? filepath : filepath + '.ndjson');\n if (lines) this.append(lines);\n }\n\n append(lines: T | T[]) {\n this.file.append(\n Array.isArray(lines) ? lines.map(l => JSON.stringify(snapshot(l))) : JSON.stringify(snapshot(lines)),\n );\n }\n\n lines() {\n return this.file.lines().map(l => JSON.parse(l) as T);\n }\n}\n\ntype Key<T extends object> = keyof T;\n\n/**\n * Comma separated values (.csv).\n * Input rows as objects, keys are used as column headers\n */\nexport class FileTypeCsv<Row extends object> extends FileType {\n constructor(filepath: string) {\n super(filepath.endsWith('.csv') ? filepath : filepath + '.csv');\n }\n\n async write(rows: Row[], keys?: Key<Row>[]) {\n const headerSet = new Set<Key<Row>>();\n if (keys) {\n for (const key of keys) headerSet.add(key);\n } else {\n for (const row of rows) {\n for (const key in row) headerSet.add(key);\n }\n }\n const headers = Array.from(headerSet);\n const outRows = rows.map(row => headers.map(key => row[key]));\n return finished(writeToStream(this.file.writeStream, [headers, ...outRows]));\n }\n\n #parseVal(val: string) {\n if (val.toLowerCase() === 'false') return false;\n if (val.toLowerCase() === 'true') return true;\n if (val.length === 0) return null;\n if (/^[\\.0-9]+$/.test(val)) return Number(val);\n return val;\n }\n\n async read() {\n return new Promise<Row[]>((resolve, reject) => {\n const parsed: Row[] = [];\n parseStream(this.file.readStream, { headers: true })\n .on('data', (raw: Record<Key<Row>, string>) => {\n parsed.push(\n Object.entries(raw).reduce(\n (all, [key, val]) => ({\n ...all,\n [key]: this.#parseVal(val as string),\n }),\n {} as Row,\n ),\n );\n })\n .on('error', e => reject(e))\n .on('end', () => resolve(parsed));\n });\n }\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport sanitizeFilename from 'sanitize-filename';\nimport { File } from './File.ts';\n\nexport type DirOptions = {\n temp?: boolean;\n};\n\n/**\n * Reference to a specific directory with methods to create and list files.\n * @param inputPath\n * The path of the directory, created on file system the first time `.path` is read or any methods are used\n * @param options\n * include `{ temp: true }` to enable the `.clear()` method\n */\nexport class Dir {\n #inputPath;\n #resolved?: string;\n isTemp;\n\n /**\n * @param path can be relative to workspace or absolute\n */\n constructor(inputPath: string, options: DirOptions = {}) {\n this.#inputPath = inputPath;\n this.isTemp = Boolean(options.temp);\n }\n\n /**\n * The path of this Dir instance. Created on file system the first time this property is read/used.\n */\n get path() {\n if (!this.#resolved) {\n this.#resolved = path.resolve(this.#inputPath);\n fs.mkdirSync(this.#resolved, { recursive: true });\n }\n return this.#resolved;\n }\n\n /**\n * Create a new Dir inside the current Dir\n * @param subPath\n * joined with parent Dir's path to make new Dir\n * @param options\n * include `{ temp: true }` to enable the `.clear()` method. If current Dir is temporary, child directories will also be temporary.\n * @example\n * const folder = new Dir('example');\n * // folder.path = '/path/to/cwd/example'\n * const child = folder.dir('path/to/dir');\n * // child.path = '/path/to/cwd/example/path/to/dir'\n */\n dir(subPath: string, options: DirOptions = { temp: this.isTemp }) {\n return new (this.constructor as typeof Dir)(path.join(this.path, subPath), options) as this;\n }\n\n /**\n * Creates a new temp directory inside current Dir\n * @param subPath joined with parent Dir's path to make new TempDir\n */\n tempDir(subPath: string) {\n return this.dir(subPath, { temp: true });\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 clear() {\n if (!this.isTemp) throw new Error('Dir is not temporary');\n fs.rmSync(this.path, { recursive: true, force: true });\n fs.mkdirSync(this.path, { recursive: true });\n }\n}\n\n/**\n * Current working directory\n */\nexport const cwd = new Dir('./');\n/**\n * ./.temp in current working directory\n */\nexport const temp = cwd.tempDir('.temp');\n","import { type Duration, isAfter, add } from 'date-fns';\nimport { Dir } 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 Dir('.cache', { temp: true });\n this.file = dir.file(key).json<{ savedAt: string; data: T }>();\n this.ttl = typeof ttl === 'number' ? { minutes: ttl } : ttl;\n if (initialData) this.write(initialData);\n }\n\n write(data: T) {\n this.file.write({ savedAt: new Date().toUTCString(), data });\n }\n\n read(): [T | undefined, boolean] {\n const { savedAt, data } = this.file.read() || {};\n const isFresh = Boolean(savedAt && isAfter(add(savedAt, this.ttl), new Date()));\n return [data, isFresh];\n }\n}\n","import { merge } from 'lodash-es';\nimport extractDomain from 'extract-domain';\n\nexport type Route = string | URL;\n\ntype QueryVal = string | number | boolean | null | undefined;\nexport type Query = Record<string, QueryVal | QueryVal[]>;\n\nexport type FetchOptions = RequestInit & {\n base?: string;\n query?: Query;\n headers?: Record<string, string>;\n data?: any;\n timeout?: number;\n retries?: number;\n retryDelay?: number;\n};\n\n/**\n * Fetcher provides a quick way to set up a basic API connection\n * with options applied to every request.\n * Includes basic methods for requesting and parsing responses\n */\nexport class Fetcher {\n defaultOptions;\n\n constructor(opts: FetchOptions = {}) {\n this.defaultOptions = {\n timeout: 60000,\n retries: 0,\n retryDelay: 3000,\n ...opts,\n };\n }\n\n /**\n * Build URL with URLSearchParams if query is provided.\n * Also returns domain, to help with cookies\n */\n buildUrl(route: Route, opts: FetchOptions = {}): [URL, string] {\n const mergedOptions = merge({}, this.defaultOptions, opts);\n const params: [string, string][] = [];\n Object.entries(mergedOptions.query || {}).forEach(([key, val]) => {\n if (val === undefined) return;\n if (Array.isArray(val)) {\n val.forEach(v => {\n params.push([key, `${v}`]);\n });\n } else {\n params.push([key, `${val}`]);\n }\n });\n const search = params.length > 0 ? '?' + new URLSearchParams(params).toString() : '';\n const url = new URL(route + search, this.defaultOptions.base);\n const domain = extractDomain(url.href) as string;\n return [url, domain];\n }\n\n /**\n * Merges options to get headers. Useful when extending the Fetcher class to add custom auth.\n */\n buildHeaders(route: Route, opts: FetchOptions = {}) {\n const { headers } = merge({}, this.defaultOptions, opts);\n return headers || {};\n }\n\n /**\n * Builds request, merging defaultOptions and provided options.\n * Includes Abort signal for timeout\n */\n buildRequest(route: Route, opts: FetchOptions = {}): [Request, FetchOptions, string] {\n const mergedOptions = merge({}, this.defaultOptions, opts);\n const { query, data, timeout, retries, ...init } = mergedOptions;\n init.headers = this.buildHeaders(route, mergedOptions);\n if (data) {\n init.headers['content-type'] = init.headers['content-type'] || 'application/json';\n init.method = init.method || 'POST';\n init.body = JSON.stringify(data);\n }\n if (timeout) {\n init.signal = AbortSignal.timeout(timeout);\n }\n const [url, domain] = this.buildUrl(route, mergedOptions);\n const req = new Request(url, init);\n return [req, mergedOptions, domain];\n }\n\n /**\n * Builds and performs the request, merging provided options with defaultOptions.\n * If `opts.data` is provided, method is updated to POST, content-type json, data is stringified in the body.\n * Retries on local or network error, with increasing backoff.\n */\n async fetch(route: Route, opts: FetchOptions = {}): Promise<[Response, Request]> {\n const [_req, options] = this.buildRequest(route, opts);\n const maxAttempts = (options.retries || 0) + 1;\n let attempt = 0;\n while (attempt < maxAttempts) {\n attempt++;\n const [req] = this.buildRequest(route, opts);\n const res = await fetch(req)\n .then(r => {\n if (!r.ok) throw new Error(r.statusText);\n return r;\n })\n .catch(async error => {\n if (attempt < maxAttempts) {\n const wait = attempt * 3000;\n console.warn(`${req.method} ${req.url} (attempt ${attempt} of ${maxAttempts})`, error);\n await new Promise(resolve => setTimeout(resolve, wait));\n } else {\n throw new Error(error);\n }\n });\n if (res) return [res, req];\n }\n throw new Error(`Failed to fetch ${_req.url}`);\n }\n\n async fetchText(route: Route, opts: FetchOptions = {}): Promise<[string, Response, Request]> {\n return this.fetch(route, opts).then(async ([res, req]) => {\n const text = await res.text();\n return [text, res, req];\n });\n }\n\n async fetchJson<T>(route: Route, opts: FetchOptions = {}): Promise<[T, Response, Request]> {\n return this.fetchText(route, opts).then(([txt, res, req]) => [JSON.parse(txt) as T, res, req]);\n }\n}\n","import { format, formatISO, type DateArg, type Duration } from 'date-fns';\nimport formatDuration from 'format-duration';\n\n/**\n * Helpers for formatting dates, times, and numbers as strings\n */\nexport class Format {\n /**\n * date-fns format() with some shortcuts\n * @param formatStr the format to use\n * @param date the date to format, default `new Date()`\n * @example\n * Format.date('iso') // '2026-04-08T13:56:45Z'\n * Format.date('ymd') // '20260408'\n * Format.date('ymd-hm') // '20260408-1356'\n * Format.date('ymd-hms') // '20260408-135645'\n * Format.date('h:m:s') // '13:56:45'\n * @see more format options https://date-fns.org/v4.1.0/docs/format\n */\n static date(\n formatStr: 'iso' | 'ymd' | 'ymd-hm' | 'ymd-hms' | 'h:m:s' | string = 'iso',\n d: DateArg<Date> = new Date(),\n ) {\n if (formatStr === 'iso') return formatISO(d);\n if (formatStr === 'ymd') return format(d, 'yyyyMMdd');\n if (formatStr === 'ymd-hm') return format(d, 'yyyyMMdd-HHmm');\n if (formatStr === 'ymd-hms') return format(d, 'yyyyMMdd-HHmmss');\n if (formatStr === 'h:m:s') return format(d, 'HH:mm:ss');\n return format(d, formatStr);\n }\n\n /**\n * Round a number to a specific set of places\n */\n static round(n: number, places = 0) {\n return new Intl.NumberFormat('en-US', { maximumFractionDigits: places }).format(n);\n }\n\n static plural(amount: number, singular: string, multiple?: string) {\n return amount === 1 ? `${amount} ${singular}` : `${amount} ${multiple || singular + 's'}`;\n }\n\n /**\n * Make millisecond durations actually readable (eg \"123ms\", \"3.56s\", \"1m 34s\", \"3h 24m\", \"2d 4h\")\n * @param ms milliseconds\n * @param style 'digital' to output as 'HH:MM:SS'\n * @see details on 'digital' format https://github.com/ungoldman/format-duration\n * @see waiting on `Intl.DurationFormat({ style: 'digital' })` types https://github.com/microsoft/TypeScript/issues/60608\n */\n static ms(ms: number, style?: 'digital') {\n if (style === 'digital') return formatDuration(ms, { leading: true });\n if (ms < 1000) return `${this.round(ms)}ms`;\n const s = ms / 1000;\n if (s < 60) return `${this.round(s, 2)}s`;\n const m = Math.floor(s / 60);\n if (m < 60) return `${m}m ${Math.floor(s) % 60}s`;\n const h = Math.floor(m / 60);\n if (h < 24) return `${h}h ${m % 60}m`;\n const d = Math.floor(h / 24);\n return `${d}d ${h % 24}h`;\n }\n\n static bytes(b: number) {\n const labels = ['b', 'KB', 'MB', 'GB', 'TB'];\n let factor = 0;\n while (b >= 1024 && labels[factor + 1]) {\n b = b / 1024;\n factor++;\n }\n return `${this.round(b, 2)} ${labels[factor]}`;\n }\n}\n","import { inspect } from 'node:util';\nimport { isObjectLike } from 'lodash-es';\nimport chalk, { type ChalkInstance } from 'chalk';\nimport { snapshot } from './snapshot.ts';\nimport { Format } from './Format.ts';\n\n// https://docs.cloud.google.com/logging/docs/reference/v2/rest/v2/LogEntry#logseverity\ntype Severity = 'DEFAULT' | 'DEBUG' | 'INFO' | 'NOTICE' | 'WARNING' | 'ERROR' | 'CRITICAL' | 'ALERT' | 'EMERGENCY';\n\ntype Options = {\n severity: Severity;\n color: ChalkInstance;\n};\n\ntype Entry = {\n message?: string;\n severity: Severity;\n stack?: string;\n details?: unknown[];\n};\n\nexport class Log {\n static getStack() {\n const details = { stack: '' };\n // replaces details.stack with current stack trace, excluding this Log.getStack call\n Error.captureStackTrace(details, Log.getStack);\n // remove 'Error' on first line\n return details.stack\n .split('\\n')\n .map(l => l.trim())\n .filter(l => l !== 'Error');\n }\n\n /**\n * Gcloud parses JSON in stdout\n */\n static #toGcloud(entry: Entry) {\n const details = entry.details?.length === 1 ? entry.details[0] : entry.details;\n const output = { ...entry, details, stack: entry.stack || this.getStack() };\n console.log(JSON.stringify(snapshot(output)));\n }\n\n /**\n * Includes colors and better inspection for logging during dev\n */\n static #toConsole(entry: Entry, color: ChalkInstance) {\n if (entry.message) console.log(color(`${Format.date('h:m:s')} [${entry.severity}] ${entry.message}`));\n entry.details?.forEach(detail => {\n console.log(inspect(detail, { depth: 10, breakLength: 100, compact: true, colors: true }));\n });\n }\n\n static #log({ severity, color }: Options, ...input: unknown[]) {\n const { message, details } = this.prepare(...input);\n const entry: Entry = { message, severity, details };\n // https://cloud.google.com/run/docs/container-contract#env-vars\n const isGcloud = process.env.K_SERVICE !== undefined || process.env.CLOUD_RUN_JOB !== undefined;\n if (isGcloud) {\n this.#toGcloud(entry);\n } else {\n this.#toConsole(entry, color);\n }\n return entry;\n }\n\n /**\n * Handle first argument being a string or an object with a 'message' prop\n */\n static prepare(...input: unknown[]): { message?: string; details: unknown[] } {\n let [firstArg, ...rest] = input;\n // First argument is a string, use that as the message\n if (typeof firstArg === 'string') {\n return { message: firstArg, details: rest };\n }\n // First argument is an object with a `message` property\n // @ts-ignore\n if (isObjectLike(firstArg) && typeof firstArg['message'] === 'string') {\n const { message, ...firstDetails } = firstArg as { message: string };\n return { message, details: [firstDetails, ...rest] };\n }\n // No message found, log all args as details\n return { details: input };\n }\n\n /**\n * Events that require action or attention immediately\n */\n static alert(...input: unknown[]) {\n return this.#log({ severity: 'ALERT', color: chalk.bgRed }, ...input);\n }\n\n /**\n * Events that cause problems\n */\n static error(...input: unknown[]) {\n return this.#log({ severity: 'ERROR', color: chalk.red }, ...input);\n }\n\n /**\n * Events that might cause problems\n */\n static warn(...input: unknown[]) {\n return this.#log({ severity: 'WARNING', color: chalk.yellow }, ...input);\n }\n\n /**\n * Normal but significant events, such as start up, shut down, or a configuration change\n */\n static notice(...input: unknown[]) {\n return this.#log({ severity: 'NOTICE', color: chalk.cyan }, ...input);\n }\n\n /**\n * Routine information, such as ongoing status or performance\n */\n static info(...input: unknown[]) {\n return this.#log({ severity: 'INFO', color: chalk.white }, ...input);\n }\n\n /**\n * Debug or trace information\n */\n static debug(...input: unknown[]) {\n return this.#log({ severity: 'DEBUG', color: chalk.gray }, ...input);\n }\n}\n","export async function timeout(ms: number) {\n return new Promise(resolve => {\n setTimeout(resolve, ms);\n });\n}\n","import * as fs from 'node:fs';\nimport { merge } from 'lodash-es';\nimport * as qt from 'quicktype-core';\n\nexport class TypeWriter {\n moduleName;\n input = qt.jsonInputForTargetLanguage('typescript');\n outDir;\n qtSettings;\n\n constructor(moduleName: string, settings: { outDir?: string } & Partial<qt.Options> = {}) {\n this.moduleName = moduleName;\n const { outDir, ...qtSettings } = settings;\n this.outDir = outDir || './types';\n const defaultSettings = {\n lang: 'typescript',\n rendererOptions: {\n 'just-types': true,\n 'prefer-types': true,\n },\n inferEnums: false,\n inferDateTimes: false,\n };\n this.qtSettings = merge(defaultSettings, qtSettings);\n }\n\n async addMember(name: string, _samples: any[]) {\n const samples = _samples.map(s => (typeof s === 'string' ? s : JSON.stringify(s)));\n await this.input.addSource({ name, samples });\n }\n\n async toString() {\n const inputData = new qt.InputData();\n inputData.addInput(this.input);\n const result = await qt.quicktype({\n inputData,\n ...this.qtSettings,\n });\n return result.lines.join('\\n');\n }\n\n async toFile() {\n const result = await this.toString();\n fs.mkdirSync(this.outDir, { recursive: true });\n fs.writeFileSync(`${this.outDir}/${this.moduleName}.d.ts`, result);\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":["output: Record<string, any>","obj: Record<string, any>","parsed: Row[]","#parseVal","#inputPath","#resolved","params: [string, string][]","timeout","#toGcloud","#toConsole","#log","entry: Entry"],"sources":["../src/snapshot.ts","../src/File.ts","../src/Dir.ts","../src/Cache.ts","../src/Fetcher.ts","../src/Format.ts","../src/Log.ts","../src/timeout.ts","../src/TypeWriter.ts"],"sourcesContent":["import { isObjectLike } from 'lodash-es';\n\n/**\n * Allows special objects (Error, Headers, Set) to be included in JSON.stringify output.\n * Functions are removed\n */\nexport function snapshot(i: unknown, max = 50, depth = 0): any {\n if (Array.isArray(i)) {\n if (depth === max) return [];\n return i.map(c => snapshot(c, max, depth + 1));\n }\n if (typeof i === 'function') return undefined;\n if (!isObjectLike(i)) return i;\n\n if (depth === max) return {};\n let output: Record<string, any> = {};\n // @ts-ignore If it has an 'entries' function, use that for looping (eg. Set, Map, Headers)\n if (typeof i.entries === 'function') {\n // @ts-ignore\n for (let [k, v] of i.entries()) {\n output[k] = snapshot(v, max, depth + 1);\n }\n return output;\n }\n\n // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Enumerability_and_ownership_of_properties\n\n // Get Enumerable, inherited properties\n const obj: Record<string, any> = i!;\n for (let key in obj) {\n output[key] = snapshot(obj[key], max, depth + 1);\n }\n\n // Get Non-enumberable, own properties\n Object.getOwnPropertyNames(obj).forEach(key => {\n output[key] = snapshot(obj[key], max, depth + 1);\n });\n\n return output;\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport { Readable } from 'node:stream';\nimport { finished } from 'node:stream/promises';\nimport mime from 'mime-types';\nimport { writeToStream, parseStream } from 'fast-csv';\nimport { snapshot } from './snapshot.ts';\n\n/**\n * Represents a file on the file system. If the file doesn't exist, it is created the first time it is written to.\n */\nexport class File {\n path;\n root;\n dir;\n base;\n name;\n ext;\n type;\n\n constructor(filepath: string) {\n this.path = path.resolve(filepath);\n const { root, dir, base, ext, name } = path.parse(this.path);\n this.root = root;\n this.dir = dir;\n this.base = base;\n this.name = name;\n this.ext = ext;\n this.type = mime.lookup(ext) || undefined;\n }\n\n get exists() {\n return fs.existsSync(this.path);\n }\n\n get stats(): Partial<fs.Stats> {\n return this.exists ? fs.statSync(this.path) : {};\n }\n\n /**\n * Deletes the file if it exists\n */\n delete() {\n fs.rmSync(this.path, { force: true });\n }\n\n /**\n * @returns the contents of the file as a string, or undefined if the file doesn't exist\n */\n read() {\n return this.exists ? fs.readFileSync(this.path, 'utf8') : undefined;\n }\n\n /**\n * @returns lines as strings, removes trailing '\\n'\n */\n lines() {\n const contents = (this.read() || '').split('\\n');\n return contents.at(-1)?.length ? contents : contents.slice(0, contents.length - 1);\n }\n\n get readStream() {\n return this.exists ? fs.createReadStream(this.path) : Readable.from([]);\n }\n\n get writeStream() {\n fs.mkdirSync(this.dir, { recursive: true });\n return fs.createWriteStream(this.path);\n }\n\n write(contents: string | ReadableStream) {\n fs.mkdirSync(this.dir, { recursive: true });\n if (typeof contents === 'string') return fs.writeFileSync(this.path, contents);\n if (contents instanceof ReadableStream) return finished(Readable.from(contents).pipe(this.writeStream));\n throw new Error(`Invalid content type: ${typeof contents}`);\n }\n\n /**\n * creates file if it doesn't exist, appends string or array of strings as new lines.\n * File always ends with '\\n', so contents don't need to be read before appending\n */\n append(lines: string | string[]) {\n if (!this.exists) this.write('');\n const contents = Array.isArray(lines) ? lines.join('\\n') : lines;\n fs.appendFileSync(this.path, contents + '\\n');\n }\n\n /**\n * @returns FileTypeJson adaptor for current File, adds '.json' extension if not present.\n * @example\n * const file = new File('./data').json({ key: 'val' }); // FileTypeJson<{ key: string; }>\n * console.log(file.path) // '/path/to/cwd/data.json'\n * file.write({ something: 'else' }) // ❌ property 'something' doesn't exist on type { key: string; }\n * @example\n * const file = new File('./data').json<object>({ key: 'val' }); // FileTypeJson<object>\n * file.write({ something: 'else' }) // ✅ data is typed as object\n */\n json<T>(contents?: T) {\n return new FileTypeJson<T>(this.path, contents);\n }\n\n /**\n * @example\n * const file = new File.json('data.json', { key: 'val' }); // FileTypeJson<{ key: string; }>\n */\n static get json() {\n return FileTypeJson;\n }\n\n /**\n * @returns FileTypeNdjson adaptor for current File, adds '.ndjson' extension if not present.\n */\n ndjson<T extends object>(lines?: T | T[]) {\n return new FileTypeNdjson<T>(this.path, lines);\n }\n /**\n * @example\n * const file = new File.ndjson('log', { key: 'val' }); // FileTypeNdjson<{ key: string; }>\n * console.log(file.path) // /path/to/cwd/log.ndjson\n */\n static get ndjson() {\n return FileTypeNdjson;\n }\n\n /**\n * @returns FileTypeCsv adaptor for current File, adds '.csv' extension if not present.\n * @example\n * const file = await new File('a').csv([{ col: 'val' }, { col: 'val2' }]); // FileTypeCsv<{ col: string; }>\n * await file.write([ { col2: 'val2' } ]); // ❌ 'col2' doesn't exist on type { col: string; }\n * await file.write({ col: 'val' }); // ✅ Writes one row\n * await file.write([{ col: 'val2' }, { col: 'val3' }]); // ✅ Writes multiple rows\n */\n async csv<T extends object>(rows?: T[], keys?: (keyof T)[]) {\n const csvFile = new FileTypeCsv<T>(this.path);\n if (rows) await csvFile.write(rows, keys);\n return csvFile;\n }\n\n static get csv() {\n return FileTypeCsv;\n }\n}\n\n/**\n * A generic file adaptor, extended by specific file type implementations\n */\nexport class FileType {\n file;\n\n constructor(filepath: string, contents?: string) {\n this.file = new File(filepath);\n if (contents) this.file.write(contents);\n }\n\n get path() {\n return this.file.path;\n }\n\n get root() {\n return this.file.root;\n }\n\n get dir() {\n return this.file.dir;\n }\n\n get base() {\n return this.file.base;\n }\n\n get name() {\n return this.file.name;\n }\n\n get ext() {\n return this.file.ext;\n }\n\n get type() {\n return this.file.type;\n }\n\n get exists() {\n return this.file.exists;\n }\n\n get stats() {\n return this.file.stats;\n }\n\n delete() {\n this.file.delete();\n }\n\n get readStream() {\n return this.file.readStream;\n }\n\n get writeStream() {\n return this.file.writeStream;\n }\n}\n\n/**\n * A .json file that maintains data type when reading/writing.\n * > ⚠️ This is mildly unsafe, important/foreign json files should be validated at runtime!\n * @example\n * const file = new FileTypeJson('./data', { key: 'val' }); // FileTypeJson<{ key: string; }>\n * console.log(file.path) // '/path/to/cwd/data.json'\n * file.write({ something: 'else' }) // ❌ property 'something' doesn't exist on type { key: string; }\n * @example\n * const file = new FileTypeJson<object>('./data', { key: 'val' }); // FileTypeJson<object>\n * file.write({ something: 'else' }) // ✅ data is typed as object\n */\nexport class FileTypeJson<T> extends FileType {\n constructor(filepath: string, contents?: T) {\n super(filepath.endsWith('.json') ? filepath : filepath + '.json');\n if (contents) this.write(contents);\n }\n\n read() {\n const contents = this.file.read();\n return contents ? (JSON.parse(contents) as T) : undefined;\n }\n\n write(contents: T) {\n this.file.write(JSON.stringify(snapshot(contents), null, 2));\n }\n}\n\n/**\n * New-line delimited json file (.ndjson)\n * @see https://jsonltools.com/ndjson-format-specification\n */\nexport class FileTypeNdjson<T extends object> extends FileType {\n constructor(filepath: string, lines?: T | T[]) {\n super(filepath.endsWith('.ndjson') ? filepath : filepath + '.ndjson');\n if (lines) this.append(lines);\n }\n\n append(lines: T | T[]) {\n this.file.append(\n Array.isArray(lines) ? lines.map(l => JSON.stringify(snapshot(l))) : JSON.stringify(snapshot(lines)),\n );\n }\n\n lines() {\n return this.file.lines().map(l => JSON.parse(l) as T);\n }\n}\n\ntype Key<T extends object> = keyof T;\n\n/**\n * Comma separated values (.csv).\n * Input rows as objects, keys are used as column headers\n */\nexport class FileTypeCsv<Row extends object> extends FileType {\n constructor(filepath: string) {\n super(filepath.endsWith('.csv') ? filepath : filepath + '.csv');\n }\n\n async write(rows: Row[], keys?: Key<Row>[]) {\n const headerSet = new Set<Key<Row>>();\n if (keys) {\n for (const key of keys) headerSet.add(key);\n } else {\n for (const row of rows) {\n for (const key in row) headerSet.add(key);\n }\n }\n const headers = Array.from(headerSet);\n const outRows = rows.map(row => headers.map(key => row[key]));\n return finished(writeToStream(this.file.writeStream, [headers, ...outRows]));\n }\n\n #parseVal(val: string) {\n if (val.toLowerCase() === 'false') return false;\n if (val.toLowerCase() === 'true') return true;\n if (val.length === 0) return null;\n if (/^[\\.0-9]+$/.test(val)) return Number(val);\n return val;\n }\n\n async read() {\n return new Promise<Row[]>((resolve, reject) => {\n const parsed: Row[] = [];\n parseStream(this.file.readStream, { headers: true })\n .on('data', (raw: Record<Key<Row>, string>) => {\n parsed.push(\n Object.entries(raw).reduce(\n (all, [key, val]) => ({\n ...all,\n [key]: this.#parseVal(val as string),\n }),\n {} as Row,\n ),\n );\n })\n .on('error', e => reject(e))\n .on('end', () => resolve(parsed));\n });\n }\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport sanitizeFilename from 'sanitize-filename';\nimport { File } from './File.ts';\n\nexport type DirOptions = {\n temp?: boolean;\n};\n\n/**\n * Reference to a specific directory with methods to create and list files.\n * @param inputPath\n * The path of the directory, created on file system the first time `.path` is read or any methods are used\n * @param options\n * include `{ temp: true }` to enable the `.clear()` method\n */\nexport class Dir {\n #inputPath;\n #resolved?: string;\n isTemp;\n\n /**\n * @param path can be relative to workspace or absolute\n */\n constructor(inputPath: string, options: DirOptions = {}) {\n this.#inputPath = inputPath;\n this.isTemp = Boolean(options.temp);\n }\n\n /**\n * The path of the directory, which might not exist yet.\n */\n get pathUnsafe() {\n return this.#resolved || path.resolve(this.#inputPath);\n }\n\n /**\n * The path of this Dir instance. Created on file system the first time this property is read/used.\n * Safe to use the directory immediately, without calling mkdir separately.\n */\n get path() {\n // avoids calling mkdir every time path is read\n if (!this.#resolved) {\n this.#resolved = this.pathUnsafe;\n fs.mkdirSync(this.#resolved, { recursive: true });\n }\n return this.#resolved;\n }\n\n /**\n * The last segment in the path. Doesn't read this.path, to avoid creating directory on file system before it's needed.\n * @example\n * const example = new Dir('/path/to/folder');\n * console.log(example.name); // \"folder\"\n */\n get name() {\n return this.pathUnsafe.split(path.sep).at(-1)!;\n }\n\n /**\n * Create a new Dir inside the current Dir\n * @param subPath\n * joined with parent Dir's path to make new Dir\n * @param options\n * include `{ temp: true }` to enable the `.clear()` method. If current Dir is temporary, child directories will also be temporary.\n * @example\n * const folder = new Dir('example');\n * // folder.path = '/path/to/cwd/example'\n * const child = folder.dir('path/to/dir');\n * // child.path = '/path/to/cwd/example/path/to/dir'\n */\n dir(subPath: string, options: DirOptions = { temp: this.isTemp }) {\n return new (this.constructor as typeof Dir)(path.join(this.path, subPath), options) as this;\n }\n\n /**\n * Creates a new temp directory inside current Dir\n * @param subPath joined with parent Dir's path to make new TempDir\n */\n tempDir(subPath: string) {\n return this.dir(subPath, { temp: true });\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 /**\n * Create a new file in this directory\n */\n file(base: string) {\n return new File(this.filepath(base));\n }\n\n /**\n * All files and subdirectories in in this directory, returned as Dir and File instances\n */\n get contents(): (Dir | File)[] {\n return fs\n .readdirSync(this.path)\n .map(name => (fs.statSync(path.join(this.path, name)).isDirectory() ? this.dir(name) : this.file(name)));\n }\n\n /**\n * All subdirectories in this directory\n */\n get dirs() {\n return this.contents.filter(f => f instanceof Dir);\n }\n\n /**\n * All files in this directory\n */\n get files() {\n return this.contents.filter(f => f instanceof File);\n }\n\n /**\n * All files with MIME type that includes \"video\"\n */\n get videos() {\n return this.files.filter(f => f.type?.includes('video'));\n }\n\n /**\n * All files with MIME type that includes \"image\"\n */\n get images() {\n return this.files.filter(f => f.type?.includes('image'));\n }\n\n /**\n * All files with ext \".json\"\n * @example\n * // Directory of json files with the same shape\n * const dataFiles = dataDir.jsonFiles.map(f => f.json<ExampleType>());\n * // dataFiles: FileTypeJson<ExampleType>[]\n */\n get jsonFiles() {\n return this.files.filter(f => f.ext === '.json');\n }\n\n /**\n * All files with ext \".ndjson\"\n * @example\n * // Directory of ndjson files with the same shape\n * const dataFiles = dataDir.ndjsonFiles.map(f => f.ndjson<ExampleType>());\n * // dataFiles: FileTypeNdjson<ExampleType>[]\n */\n get ndjsonFiles() {\n return this.files.filter(f => f.ext === '.ndjson');\n }\n\n /**\n * All files with ext \".csv\"\n * @example\n * // Directory of csv files with the same shape\n * const dataFiles = dataDir.csvFile.map(f => f.csv<ExampleType>());\n * // dataFiles: FileTypeCsv<ExampleType>[]\n */\n get csvFiles() {\n return this.files.filter(f => f.ext === '.csv');\n }\n\n /**\n * All files with ext \".txt\"\n */\n get textFiles() {\n return this.files.filter(f => f.ext === '.txt');\n }\n\n /**\n * Deletes the contents of the directory. Only allowed if created with `temp` option set to `true` (or created with `dir.tempDir` method).\n */\n clear() {\n if (!this.isTemp) throw new Error('Dir is not temporary');\n fs.rmSync(this.path, { recursive: true, force: true });\n fs.mkdirSync(this.path, { recursive: true });\n }\n}\n\n/**\n * Current working directory\n */\nexport const cwd = new Dir('./');\n/**\n * ./.temp in current working directory\n */\nexport const temp = cwd.tempDir('.temp');\n","import { type Duration, isAfter, add } from 'date-fns';\nimport { Dir } 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 Dir('.cache', { temp: true });\n this.file = dir.file(key).json<{ savedAt: string; data: T }>();\n this.ttl = typeof ttl === 'number' ? { minutes: ttl } : ttl;\n if (initialData) this.write(initialData);\n }\n\n write(data: T) {\n this.file.write({ savedAt: new Date().toUTCString(), data });\n }\n\n read(): [T | undefined, boolean] {\n const { savedAt, data } = this.file.read() || {};\n const isFresh = Boolean(savedAt && isAfter(add(savedAt, this.ttl), new Date()));\n return [data, isFresh];\n }\n}\n","import { merge } from 'lodash-es';\nimport extractDomain from 'extract-domain';\n\nexport type Route = string | URL;\n\ntype QueryVal = string | number | boolean | null | undefined;\nexport type Query = Record<string, QueryVal | QueryVal[]>;\n\nexport type FetchOptions = RequestInit & {\n base?: string;\n query?: Query;\n headers?: Record<string, string>;\n data?: any;\n timeout?: number;\n retries?: number;\n retryDelay?: number;\n};\n\n/**\n * Fetcher provides a quick way to set up a basic API connection\n * with options applied to every request.\n * Includes basic methods for requesting and parsing responses\n */\nexport class Fetcher {\n defaultOptions;\n\n constructor(opts: FetchOptions = {}) {\n this.defaultOptions = {\n timeout: 60000,\n retries: 0,\n retryDelay: 3000,\n ...opts,\n };\n }\n\n /**\n * Build URL with URLSearchParams if query is provided.\n * Also returns domain, to help with cookies\n */\n buildUrl(route: Route, opts: FetchOptions = {}): [URL, string] {\n const mergedOptions = merge({}, this.defaultOptions, opts);\n const params: [string, string][] = [];\n Object.entries(mergedOptions.query || {}).forEach(([key, val]) => {\n if (val === undefined) return;\n if (Array.isArray(val)) {\n val.forEach(v => {\n params.push([key, `${v}`]);\n });\n } else {\n params.push([key, `${val}`]);\n }\n });\n const search = params.length > 0 ? '?' + new URLSearchParams(params).toString() : '';\n const url = new URL(route + search, this.defaultOptions.base);\n const domain = extractDomain(url.href) as string;\n return [url, domain];\n }\n\n /**\n * Merges options to get headers. Useful when extending the Fetcher class to add custom auth.\n */\n buildHeaders(route: Route, opts: FetchOptions = {}) {\n const { headers } = merge({}, this.defaultOptions, opts);\n return headers || {};\n }\n\n /**\n * Builds request, merging defaultOptions and provided options.\n * Includes Abort signal for timeout\n */\n buildRequest(route: Route, opts: FetchOptions = {}): [Request, FetchOptions, string] {\n const mergedOptions = merge({}, this.defaultOptions, opts);\n const { query, data, timeout, retries, ...init } = mergedOptions;\n init.headers = this.buildHeaders(route, mergedOptions);\n if (data) {\n init.headers['content-type'] = init.headers['content-type'] || 'application/json';\n init.method = init.method || 'POST';\n init.body = JSON.stringify(data);\n }\n if (timeout) {\n init.signal = AbortSignal.timeout(timeout);\n }\n const [url, domain] = this.buildUrl(route, mergedOptions);\n const req = new Request(url, init);\n return [req, mergedOptions, domain];\n }\n\n /**\n * Builds and performs the request, merging provided options with defaultOptions.\n * If `opts.data` is provided, method is updated to POST, content-type json, data is stringified in the body.\n * Retries on local or network error, with increasing backoff.\n */\n async fetch(route: Route, opts: FetchOptions = {}): Promise<[Response, Request]> {\n const [_req, options] = this.buildRequest(route, opts);\n const maxAttempts = (options.retries || 0) + 1;\n let attempt = 0;\n while (attempt < maxAttempts) {\n attempt++;\n const [req] = this.buildRequest(route, opts);\n const res = await fetch(req)\n .then(r => {\n if (!r.ok) throw new Error(r.statusText);\n return r;\n })\n .catch(async error => {\n if (attempt < maxAttempts) {\n const wait = attempt * 3000;\n console.warn(`${req.method} ${req.url} (attempt ${attempt} of ${maxAttempts})`, error);\n await new Promise(resolve => setTimeout(resolve, wait));\n } else {\n throw new Error(error);\n }\n });\n if (res) return [res, req];\n }\n throw new Error(`Failed to fetch ${_req.url}`);\n }\n\n async fetchText(route: Route, opts: FetchOptions = {}): Promise<[string, Response, Request]> {\n return this.fetch(route, opts).then(async ([res, req]) => {\n const text = await res.text();\n return [text, res, req];\n });\n }\n\n async fetchJson<T>(route: Route, opts: FetchOptions = {}): Promise<[T, Response, Request]> {\n return this.fetchText(route, opts).then(([txt, res, req]) => [JSON.parse(txt) as T, res, req]);\n }\n}\n","import { format, formatISO, type DateArg, type Duration } from 'date-fns';\nimport formatDuration from 'format-duration';\n\n/**\n * Helpers for formatting dates, times, and numbers as strings\n */\nexport class Format {\n /**\n * date-fns format() with some shortcuts\n * @param formatStr the format to use\n * @param date the date to format, default `new Date()`\n * @example\n * Format.date('iso') // '2026-04-08T13:56:45Z'\n * Format.date('ymd') // '20260408'\n * Format.date('ymd-hm') // '20260408-1356'\n * Format.date('ymd-hms') // '20260408-135645'\n * Format.date('h:m:s') // '13:56:45'\n * @see more format options https://date-fns.org/v4.1.0/docs/format\n */\n static date(\n formatStr: 'iso' | 'ymd' | 'ymd-hm' | 'ymd-hms' | 'h:m:s' | string = 'iso',\n d: DateArg<Date> = new Date(),\n ) {\n if (formatStr === 'iso') return formatISO(d);\n if (formatStr === 'ymd') return format(d, 'yyyyMMdd');\n if (formatStr === 'ymd-hm') return format(d, 'yyyyMMdd-HHmm');\n if (formatStr === 'ymd-hms') return format(d, 'yyyyMMdd-HHmmss');\n if (formatStr === 'h:m:s') return format(d, 'HH:mm:ss');\n return format(d, formatStr);\n }\n\n /**\n * Round a number to a specific set of places\n */\n static round(n: number, places = 0) {\n return new Intl.NumberFormat('en-US', { maximumFractionDigits: places }).format(n);\n }\n\n static plural(amount: number, singular: string, multiple?: string) {\n return amount === 1 ? `${amount} ${singular}` : `${amount} ${multiple || singular + 's'}`;\n }\n\n /**\n * Make millisecond durations actually readable (eg \"123ms\", \"3.56s\", \"1m 34s\", \"3h 24m\", \"2d 4h\")\n * @param ms milliseconds\n * @param style 'digital' to output as 'HH:MM:SS'\n * @see details on 'digital' format https://github.com/ungoldman/format-duration\n * @see waiting on `Intl.DurationFormat({ style: 'digital' })` types https://github.com/microsoft/TypeScript/issues/60608\n */\n static ms(ms: number, style?: 'digital') {\n if (style === 'digital') return formatDuration(ms, { leading: true });\n if (ms < 1000) return `${this.round(ms)}ms`;\n const s = ms / 1000;\n if (s < 60) return `${this.round(s, 2)}s`;\n const m = Math.floor(s / 60);\n if (m < 60) return `${m}m ${Math.floor(s) % 60}s`;\n const h = Math.floor(m / 60);\n if (h < 24) return `${h}h ${m % 60}m`;\n const d = Math.floor(h / 24);\n return `${d}d ${h % 24}h`;\n }\n\n static bytes(b: number) {\n const labels = ['b', 'KB', 'MB', 'GB', 'TB'];\n let factor = 0;\n while (b >= 1024 && labels[factor + 1]) {\n b = b / 1024;\n factor++;\n }\n return `${this.round(b, 2)} ${labels[factor]}`;\n }\n}\n","import { inspect } from 'node:util';\nimport { isObjectLike } from 'lodash-es';\nimport chalk, { type ChalkInstance } from 'chalk';\nimport { snapshot } from './snapshot.ts';\nimport { Format } from './Format.ts';\n\n// https://docs.cloud.google.com/logging/docs/reference/v2/rest/v2/LogEntry#logseverity\ntype Severity = 'DEFAULT' | 'DEBUG' | 'INFO' | 'NOTICE' | 'WARNING' | 'ERROR' | 'CRITICAL' | 'ALERT' | 'EMERGENCY';\n\ntype Options = {\n severity: Severity;\n color: ChalkInstance;\n};\n\ntype Entry = {\n message?: string;\n severity: Severity;\n stack?: string;\n details?: unknown[];\n};\n\nexport class Log {\n static getStack() {\n const details = { stack: '' };\n // replaces details.stack with current stack trace, excluding this Log.getStack call\n Error.captureStackTrace(details, Log.getStack);\n // remove 'Error' on first line\n return details.stack\n .split('\\n')\n .map(l => l.trim())\n .filter(l => l !== 'Error');\n }\n\n /**\n * Gcloud parses JSON in stdout\n */\n static #toGcloud(entry: Entry) {\n const details = entry.details?.length === 1 ? entry.details[0] : entry.details;\n const output = { ...entry, details, stack: entry.stack || this.getStack() };\n console.log(JSON.stringify(snapshot(output)));\n }\n\n /**\n * Includes colors and better inspection for logging during dev\n */\n static #toConsole(entry: Entry, color: ChalkInstance) {\n if (entry.message) console.log(color(`${Format.date('h:m:s')} [${entry.severity}] ${entry.message}`));\n entry.details?.forEach(detail => {\n console.log(inspect(detail, { depth: 10, breakLength: 100, compact: true, colors: true }));\n });\n }\n\n static #log({ severity, color }: Options, ...input: unknown[]) {\n const { message, details } = this.prepare(...input);\n const entry: Entry = { message, severity, details };\n // https://cloud.google.com/run/docs/container-contract#env-vars\n const isGcloud = process.env.K_SERVICE !== undefined || process.env.CLOUD_RUN_JOB !== undefined;\n if (isGcloud) {\n this.#toGcloud(entry);\n } else {\n this.#toConsole(entry, color);\n }\n return entry;\n }\n\n /**\n * Handle first argument being a string or an object with a 'message' prop\n */\n static prepare(...input: unknown[]): { message?: string; details: unknown[] } {\n let [firstArg, ...rest] = input;\n // First argument is a string, use that as the message\n if (typeof firstArg === 'string') {\n return { message: firstArg, details: rest };\n }\n // First argument is an object with a `message` property\n // @ts-ignore\n if (isObjectLike(firstArg) && typeof firstArg['message'] === 'string') {\n const { message, ...firstDetails } = firstArg as { message: string };\n return { message, details: [firstDetails, ...rest] };\n }\n // No message found, log all args as details\n return { details: input };\n }\n\n /**\n * Events that require action or attention immediately\n */\n static alert(...input: unknown[]) {\n return this.#log({ severity: 'ALERT', color: chalk.bgRed }, ...input);\n }\n\n /**\n * Events that cause problems\n */\n static error(...input: unknown[]) {\n return this.#log({ severity: 'ERROR', color: chalk.red }, ...input);\n }\n\n /**\n * Events that might cause problems\n */\n static warn(...input: unknown[]) {\n return this.#log({ severity: 'WARNING', color: chalk.yellow }, ...input);\n }\n\n /**\n * Normal but significant events, such as start up, shut down, or a configuration change\n */\n static notice(...input: unknown[]) {\n return this.#log({ severity: 'NOTICE', color: chalk.cyan }, ...input);\n }\n\n /**\n * Routine information, such as ongoing status or performance\n */\n static info(...input: unknown[]) {\n return this.#log({ severity: 'INFO', color: chalk.white }, ...input);\n }\n\n /**\n * Debug or trace information\n */\n static debug(...input: unknown[]) {\n return this.#log({ severity: 'DEBUG', color: chalk.gray }, ...input);\n }\n}\n","export async function timeout(ms: number) {\n return new Promise(resolve => {\n setTimeout(resolve, ms);\n });\n}\n","import * as fs from 'node:fs';\nimport { merge } from 'lodash-es';\nimport * as qt from 'quicktype-core';\n\nexport class TypeWriter {\n moduleName;\n input = qt.jsonInputForTargetLanguage('typescript');\n outDir;\n qtSettings;\n\n constructor(moduleName: string, settings: { outDir?: string } & Partial<qt.Options> = {}) {\n this.moduleName = moduleName;\n const { outDir, ...qtSettings } = settings;\n this.outDir = outDir || './types';\n const defaultSettings = {\n lang: 'typescript',\n rendererOptions: {\n 'just-types': true,\n 'prefer-types': true,\n },\n inferEnums: false,\n inferDateTimes: false,\n };\n this.qtSettings = merge(defaultSettings, qtSettings);\n }\n\n async addMember(name: string, _samples: any[]) {\n const samples = _samples.map(s => (typeof s === 'string' ? s : JSON.stringify(s)));\n await this.input.addSource({ name, samples });\n }\n\n async toString() {\n const inputData = new qt.InputData();\n inputData.addInput(this.input);\n const result = await qt.quicktype({\n inputData,\n ...this.qtSettings,\n });\n return result.lines.join('\\n');\n }\n\n async toFile() {\n const result = await this.toString();\n fs.mkdirSync(this.outDir, { recursive: true });\n fs.writeFileSync(`${this.outDir}/${this.moduleName}.d.ts`, result);\n }\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brianbuie/node-kit",
3
- "version": "0.13.0",
3
+ "version": "0.14.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
@@ -4,6 +4,7 @@ import { temp, Dir, type DirOptions } from './Dir.ts';
4
4
 
5
5
  describe('Dir', () => {
6
6
  const testDir = temp.dir('dir-test');
7
+ testDir.clear();
7
8
 
8
9
  it('Sanitizes filenames', () => {
9
10
  const name = testDir.sanitize(':/something/else.json');
@@ -16,6 +17,7 @@ describe('Dir', () => {
16
17
  const sub = testDir.dir(subPath);
17
18
  assert(sub.path.includes(testDir.path));
18
19
  assert(sub.path.includes(subPath));
20
+ assert(testDir.dirs.length > 0);
19
21
  });
20
22
 
21
23
  it('.tempDir returns temporary directory', () => {
@@ -41,16 +43,18 @@ describe('Dir', () => {
41
43
 
42
44
  it('is extendable and chains methods correctly', () => {
43
45
  class Example extends Dir {
44
- get jsonFiles() {
45
- return this.files.filter(f => f.ext === '.json');
46
+ get testFiles() {
47
+ return this.files.filter(f => f.ext === '.test');
46
48
  }
47
49
  }
48
50
  const testRoot = testDir.tempDir('extendable');
49
51
  const test = new Example(testRoot.path);
50
52
  const child = test.dir('child');
51
53
  assert(child instanceof Example);
52
- child.file('child.json').json({});
53
- assert(child.jsonFiles.length === 1);
54
+ const childFile = child.file('child.test');
55
+ childFile.write('');
56
+ assert(child.testFiles.map(f => f.path).includes(childFile.path));
57
+ assert(test.dirs.map(d => d.path).includes(child.path));
54
58
  const childTemp = child.tempDir('temp-child');
55
59
  assert(childTemp instanceof Example);
56
60
  childTemp.file('child-temp').json({});
package/src/Dir.ts CHANGED
@@ -27,17 +27,36 @@ export class Dir {
27
27
  this.isTemp = Boolean(options.temp);
28
28
  }
29
29
 
30
+ /**
31
+ * The path of the directory, which might not exist yet.
32
+ */
33
+ get pathUnsafe() {
34
+ return this.#resolved || path.resolve(this.#inputPath);
35
+ }
36
+
30
37
  /**
31
38
  * The path of this Dir instance. Created on file system the first time this property is read/used.
39
+ * Safe to use the directory immediately, without calling mkdir separately.
32
40
  */
33
41
  get path() {
42
+ // avoids calling mkdir every time path is read
34
43
  if (!this.#resolved) {
35
- this.#resolved = path.resolve(this.#inputPath);
44
+ this.#resolved = this.pathUnsafe;
36
45
  fs.mkdirSync(this.#resolved, { recursive: true });
37
46
  }
38
47
  return this.#resolved;
39
48
  }
40
49
 
50
+ /**
51
+ * The last segment in the path. Doesn't read this.path, to avoid creating directory on file system before it's needed.
52
+ * @example
53
+ * const example = new Dir('/path/to/folder');
54
+ * console.log(example.name); // "folder"
55
+ */
56
+ get name() {
57
+ return this.pathUnsafe.split(path.sep).at(-1)!;
58
+ }
59
+
41
60
  /**
42
61
  * Create a new Dir inside the current Dir
43
62
  * @param subPath
@@ -78,14 +97,93 @@ export class Dir {
78
97
  return path.resolve(this.path, this.sanitize(base));
79
98
  }
80
99
 
100
+ /**
101
+ * Create a new file in this directory
102
+ */
81
103
  file(base: string) {
82
104
  return new File(this.filepath(base));
83
105
  }
84
106
 
107
+ /**
108
+ * All files and subdirectories in in this directory, returned as Dir and File instances
109
+ */
110
+ get contents(): (Dir | File)[] {
111
+ return fs
112
+ .readdirSync(this.path)
113
+ .map(name => (fs.statSync(path.join(this.path, name)).isDirectory() ? this.dir(name) : this.file(name)));
114
+ }
115
+
116
+ /**
117
+ * All subdirectories in this directory
118
+ */
119
+ get dirs() {
120
+ return this.contents.filter(f => f instanceof Dir);
121
+ }
122
+
123
+ /**
124
+ * All files in this directory
125
+ */
85
126
  get files() {
86
- return fs.readdirSync(this.path).map(filename => this.file(filename));
127
+ return this.contents.filter(f => f instanceof File);
128
+ }
129
+
130
+ /**
131
+ * All files with MIME type that includes "video"
132
+ */
133
+ get videos() {
134
+ return this.files.filter(f => f.type?.includes('video'));
87
135
  }
88
136
 
137
+ /**
138
+ * All files with MIME type that includes "image"
139
+ */
140
+ get images() {
141
+ return this.files.filter(f => f.type?.includes('image'));
142
+ }
143
+
144
+ /**
145
+ * All files with ext ".json"
146
+ * @example
147
+ * // Directory of json files with the same shape
148
+ * const dataFiles = dataDir.jsonFiles.map(f => f.json<ExampleType>());
149
+ * // dataFiles: FileTypeJson<ExampleType>[]
150
+ */
151
+ get jsonFiles() {
152
+ return this.files.filter(f => f.ext === '.json');
153
+ }
154
+
155
+ /**
156
+ * All files with ext ".ndjson"
157
+ * @example
158
+ * // Directory of ndjson files with the same shape
159
+ * const dataFiles = dataDir.ndjsonFiles.map(f => f.ndjson<ExampleType>());
160
+ * // dataFiles: FileTypeNdjson<ExampleType>[]
161
+ */
162
+ get ndjsonFiles() {
163
+ return this.files.filter(f => f.ext === '.ndjson');
164
+ }
165
+
166
+ /**
167
+ * All files with ext ".csv"
168
+ * @example
169
+ * // Directory of csv files with the same shape
170
+ * const dataFiles = dataDir.csvFile.map(f => f.csv<ExampleType>());
171
+ * // dataFiles: FileTypeCsv<ExampleType>[]
172
+ */
173
+ get csvFiles() {
174
+ return this.files.filter(f => f.ext === '.csv');
175
+ }
176
+
177
+ /**
178
+ * All files with ext ".txt"
179
+ */
180
+ get textFiles() {
181
+ return this.files.filter(f => f.ext === '.txt');
182
+ }
183
+
184
+ /**
185
+ * Deletes the contents of the directory. Only allowed if created with `temp` option set to `true` (or created with `dir.tempDir` method).
186
+ */
89
187
  clear() {
90
188
  if (!this.isTemp) throw new Error('Dir is not temporary');
91
189
  fs.rmSync(this.path, { recursive: true, force: true });
@@ -1,6 +0,0 @@
1
- export default {
2
- printWidth: 120,
3
- singleQuote: true,
4
- quoteProps: 'consistent',
5
- arrowParens: 'avoid',
6
- };