@brianbuie/node-kit 0.9.1 → 0.10.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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/File.ts","../src/Dir.ts","../src/Cache.ts","../src/Fetcher.ts","../src/Log.ts","../src/snapshot.ts","../src/timeout.ts","../src/TypeWriter.ts"],"sourcesContent":[],"mappings":"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"}
package/dist/index.mjs ADDED
@@ -0,0 +1,573 @@
1
+ import * as fs from "node:fs";
2
+ import * as path from "node:path";
3
+ import sanitizeFilename from "sanitize-filename";
4
+ import { Readable } from "node:stream";
5
+ import { finished } from "node:stream/promises";
6
+ import { parseStream, writeToStream } from "fast-csv";
7
+ import { isObjectLike, merge } from "lodash-es";
8
+ import { add, isAfter } from "date-fns";
9
+ import extractDomain from "extract-domain";
10
+ import { inspect } from "node:util";
11
+ import chalk from "chalk";
12
+ import * as qt from "quicktype-core";
13
+
14
+ //#region src/snapshot.ts
15
+ /**
16
+ * Allows special objects (Error, Headers, Set) to be included in JSON.stringify output
17
+ * functions are removed
18
+ */
19
+ function snapshot(i, max = 50, depth = 0) {
20
+ if (Array.isArray(i)) {
21
+ if (depth === max) return [];
22
+ return i.map((c) => snapshot(c, max, depth + 1));
23
+ }
24
+ if (typeof i === "function") return void 0;
25
+ if (!isObjectLike(i)) return i;
26
+ if (depth === max) return {};
27
+ let output = {};
28
+ if (typeof i.entries === "function") {
29
+ for (let [k, v] of i.entries()) output[k] = snapshot(v, max, depth + 1);
30
+ return output;
31
+ }
32
+ const obj = i;
33
+ for (let key in obj) output[key] = snapshot(obj[key], max, depth + 1);
34
+ Object.getOwnPropertyNames(obj).forEach((key) => {
35
+ output[key] = snapshot(obj[key], max, depth + 1);
36
+ });
37
+ return output;
38
+ }
39
+
40
+ //#endregion
41
+ //#region src/File.ts
42
+ /**
43
+ * WARNING: API will change!
44
+ */
45
+ var File = class {
46
+ path;
47
+ root;
48
+ dir;
49
+ base;
50
+ ext;
51
+ name;
52
+ constructor(filepath) {
53
+ this.path = filepath;
54
+ const { root, dir, base, ext, name } = path.parse(filepath);
55
+ this.root = root;
56
+ this.dir = dir;
57
+ this.base = base;
58
+ this.ext = ext;
59
+ this.name = name;
60
+ }
61
+ get exists() {
62
+ return fs.existsSync(this.path);
63
+ }
64
+ delete() {
65
+ fs.rmSync(this.path, { force: true });
66
+ }
67
+ read() {
68
+ return this.exists ? fs.readFileSync(this.path, "utf8") : void 0;
69
+ }
70
+ /**
71
+ * @returns lines as strings, removes trailing '\n'
72
+ */
73
+ lines() {
74
+ const contents = (this.read() || "").split("\n");
75
+ return contents.slice(0, contents.length - 1);
76
+ }
77
+ get readStream() {
78
+ return this.exists ? fs.createReadStream(this.path) : Readable.from([]);
79
+ }
80
+ get writeStream() {
81
+ fs.mkdirSync(path.parse(this.path).dir, { recursive: true });
82
+ return fs.createWriteStream(this.path);
83
+ }
84
+ write(contents) {
85
+ fs.mkdirSync(path.parse(this.path).dir, { recursive: true });
86
+ if (typeof contents === "string") return fs.writeFileSync(this.path, contents);
87
+ if (contents instanceof ReadableStream) return finished(Readable.from(contents).pipe(this.writeStream));
88
+ throw new Error(`Invalid content type: ${typeof contents}`);
89
+ }
90
+ /**
91
+ * creates file if it doesn't exist, appends string or array of strings as new lines.
92
+ * File always ends with '\n', so contents don't need to be read before appending
93
+ */
94
+ append(lines) {
95
+ if (!this.exists) this.write("");
96
+ const contents = Array.isArray(lines) ? lines.join("\n") : lines;
97
+ fs.appendFileSync(this.path, contents + "\n");
98
+ }
99
+ static get FileType() {
100
+ return FileType;
101
+ }
102
+ json(contents) {
103
+ return new FileTypeJson(this.path, contents);
104
+ }
105
+ static get json() {
106
+ return FileTypeJson;
107
+ }
108
+ ndjson(lines) {
109
+ return new FileTypeNdjson(this.path, lines);
110
+ }
111
+ static get ndjson() {
112
+ return FileTypeNdjson;
113
+ }
114
+ async csv(rows, keys) {
115
+ const csvFile = new FileTypeCsv(this.path);
116
+ if (rows) await csvFile.write(rows, keys);
117
+ return csvFile;
118
+ }
119
+ static get csv() {
120
+ return FileTypeCsv;
121
+ }
122
+ };
123
+ /**
124
+ * A generic file adaptor, extended by specific file type implementations
125
+ */
126
+ var FileType = class {
127
+ file;
128
+ constructor(filepath, contents) {
129
+ this.file = new File(filepath);
130
+ if (contents) this.file.write(contents);
131
+ }
132
+ get exists() {
133
+ return this.file.exists;
134
+ }
135
+ get path() {
136
+ return this.file.path;
137
+ }
138
+ delete() {
139
+ this.file.delete();
140
+ }
141
+ };
142
+ /**
143
+ * A .json file that maintains data type when reading/writing.
144
+ * This is unsafe! Type is not checked at runtime, avoid using on files manipulated outside of your application.
145
+ */
146
+ var FileTypeJson = class extends FileType {
147
+ constructor(filepath, contents) {
148
+ super(filepath.endsWith(".json") ? filepath : filepath + ".json");
149
+ if (contents) this.write(contents);
150
+ }
151
+ read() {
152
+ const contents = this.file.read();
153
+ return contents ? JSON.parse(contents) : void 0;
154
+ }
155
+ write(contents) {
156
+ this.file.write(JSON.stringify(snapshot(contents), null, 2));
157
+ }
158
+ };
159
+ /**
160
+ * New-line delimited json file (.ndjson)
161
+ * @see https://jsonltools.com/ndjson-format-specification
162
+ */
163
+ var FileTypeNdjson = class extends FileType {
164
+ constructor(filepath, lines) {
165
+ super(filepath.endsWith(".ndjson") ? filepath : filepath + ".ndjson");
166
+ if (lines) this.append(lines);
167
+ }
168
+ append(lines) {
169
+ this.file.append(Array.isArray(lines) ? lines.map((l) => JSON.stringify(snapshot(l))) : JSON.stringify(snapshot(lines)));
170
+ }
171
+ lines() {
172
+ return this.file.lines().map((l) => JSON.parse(l));
173
+ }
174
+ };
175
+ /**
176
+ * Comma separated values (.csv).
177
+ * Input rows as objects, keys are used as column headers
178
+ */
179
+ var FileTypeCsv = class extends FileType {
180
+ constructor(filepath) {
181
+ super(filepath.endsWith(".csv") ? filepath : filepath + ".csv");
182
+ }
183
+ async write(rows, keys) {
184
+ const headerSet = /* @__PURE__ */ new Set();
185
+ if (keys) for (const key of keys) headerSet.add(key);
186
+ else for (const row of rows) for (const key in row) headerSet.add(key);
187
+ const headers = Array.from(headerSet);
188
+ const outRows = rows.map((row) => headers.map((key) => row[key]));
189
+ return finished(writeToStream(this.file.writeStream, [headers, ...outRows]));
190
+ }
191
+ #parseVal(val) {
192
+ if (val.toLowerCase() === "false") return false;
193
+ if (val.toLowerCase() === "true") return true;
194
+ if (val.length === 0) return null;
195
+ if (/^[\.0-9]+$/.test(val)) return Number(val);
196
+ return val;
197
+ }
198
+ async read() {
199
+ return new Promise((resolve, reject) => {
200
+ const parsed = [];
201
+ parseStream(this.file.readStream, { headers: true }).on("error", (e) => reject(e)).on("data", (raw) => {
202
+ parsed.push(Object.entries(raw).reduce((all, [key, val]) => ({
203
+ ...all,
204
+ [key]: this.#parseVal(val)
205
+ }), {}));
206
+ }).on("end", () => resolve(parsed));
207
+ });
208
+ }
209
+ };
210
+
211
+ //#endregion
212
+ //#region src/Dir.ts
213
+ /**
214
+ * Reference to a specific directory with helpful methods for resolving filepaths,
215
+ * sanitizing filenames, and saving files.
216
+ */
217
+ var Dir = class Dir {
218
+ path;
219
+ /**
220
+ * @param path can be relative to workspace or absolute
221
+ */
222
+ constructor(_path = "./") {
223
+ this.path = path.resolve(_path);
224
+ }
225
+ create() {
226
+ fs.mkdirSync(this.path, { recursive: true });
227
+ }
228
+ /**
229
+ * Create a new Dir inside the current Dir
230
+ * @param subPath to create in current Dir
231
+ * @example
232
+ * const folder = new Dir('example');
233
+ * // folder.path = './example'
234
+ * const child = folder.dir('path/to/dir');
235
+ * // child.path = './example/path/to/dir'
236
+ */
237
+ dir(subPath) {
238
+ return new Dir(path.resolve(this.path, subPath));
239
+ }
240
+ tempDir(subPath) {
241
+ return new TempDir(path.resolve(this.path, subPath));
242
+ }
243
+ sanitize(name) {
244
+ return sanitizeFilename(name.replace("https://", "").replace("www.", ""), { replacement: "_" }).slice(-200);
245
+ }
246
+ /**
247
+ * @param base - The file name with extension
248
+ * @example
249
+ * const folder = new Dir('example');
250
+ * const filepath = folder.resolve('file.json');
251
+ * // 'example/file.json'
252
+ */
253
+ filepath(base) {
254
+ return path.resolve(this.path, this.sanitize(base));
255
+ }
256
+ file(base) {
257
+ return new File(this.filepath(base));
258
+ }
259
+ };
260
+ /**
261
+ * Extends Dir class with method to `clear()` contents
262
+ */
263
+ var TempDir = class extends Dir {
264
+ clear() {
265
+ fs.rmSync(this.path, {
266
+ recursive: true,
267
+ force: true
268
+ });
269
+ this.create();
270
+ }
271
+ };
272
+ /**
273
+ * Common temp dir location
274
+ */
275
+ const temp = new TempDir(".temp");
276
+
277
+ //#endregion
278
+ //#region src/Cache.ts
279
+ const cacheDir = temp.dir("cache");
280
+ /**
281
+ * Save data to a local file with an expiration.
282
+ * Fresh/stale data is returned with a flag for if it's fresh or not,
283
+ * so stale data can still be used if needed.
284
+ */
285
+ var Cache = class {
286
+ file;
287
+ ttl;
288
+ constructor(key, ttl, initialData) {
289
+ this.file = cacheDir.file(key).json();
290
+ this.ttl = typeof ttl === "number" ? { minutes: ttl } : ttl;
291
+ if (initialData) this.write(initialData);
292
+ }
293
+ write(data) {
294
+ this.file.write({
295
+ savedAt: (/* @__PURE__ */ new Date()).toUTCString(),
296
+ data
297
+ });
298
+ }
299
+ read() {
300
+ const { savedAt, data } = this.file.read() || {};
301
+ return [data, Boolean(savedAt && isAfter(add(savedAt, this.ttl), /* @__PURE__ */ new Date()))];
302
+ }
303
+ };
304
+
305
+ //#endregion
306
+ //#region src/Fetcher.ts
307
+ /**
308
+ * Fetcher provides a quick way to set up a basic API connection
309
+ * with options applied to every request.
310
+ * Includes basic methods for requesting and parsing responses
311
+ */
312
+ var Fetcher = class {
313
+ defaultOptions;
314
+ constructor(opts = {}) {
315
+ this.defaultOptions = {
316
+ timeout: 6e4,
317
+ retries: 0,
318
+ retryDelay: 3e3,
319
+ ...opts
320
+ };
321
+ }
322
+ /**
323
+ * Build URL with URLSearchParams if query is provided.
324
+ * Also returns domain, to help with cookies
325
+ */
326
+ buildUrl(route, opts = {}) {
327
+ const mergedOptions = merge({}, this.defaultOptions, opts);
328
+ const params = [];
329
+ Object.entries(mergedOptions.query || {}).forEach(([key, val]) => {
330
+ if (val === void 0) return;
331
+ if (Array.isArray(val)) val.forEach((v) => {
332
+ params.push([key, `${v}`]);
333
+ });
334
+ else params.push([key, `${val}`]);
335
+ });
336
+ const search = params.length > 0 ? "?" + new URLSearchParams(params).toString() : "";
337
+ const url = new URL(route + search, this.defaultOptions.base);
338
+ return [url, extractDomain(url.href)];
339
+ }
340
+ /**
341
+ * Merges options to get headers. Useful when extending the Fetcher class to add custom auth.
342
+ */
343
+ buildHeaders(route, opts = {}) {
344
+ const { headers } = merge({}, this.defaultOptions, opts);
345
+ return headers || {};
346
+ }
347
+ /**
348
+ * Builds request, merging defaultOptions and provided options.
349
+ * Includes Abort signal for timeout
350
+ */
351
+ buildRequest(route, opts = {}) {
352
+ const mergedOptions = merge({}, this.defaultOptions, opts);
353
+ const { query, data, timeout: timeout$1, retries, ...init } = mergedOptions;
354
+ init.headers = this.buildHeaders(route, mergedOptions);
355
+ if (data) {
356
+ init.headers["content-type"] = init.headers["content-type"] || "application/json";
357
+ init.method = init.method || "POST";
358
+ init.body = JSON.stringify(data);
359
+ }
360
+ if (timeout$1) init.signal = AbortSignal.timeout(timeout$1);
361
+ const [url, domain] = this.buildUrl(route, mergedOptions);
362
+ return [
363
+ new Request(url, init),
364
+ mergedOptions,
365
+ domain
366
+ ];
367
+ }
368
+ /**
369
+ * Builds and performs the request, merging provided options with defaultOptions.
370
+ * If `opts.data` is provided, method is updated to POST, content-type json, data is stringified in the body.
371
+ * Retries on local or network error, with increasing backoff.
372
+ */
373
+ async fetch(route, opts = {}) {
374
+ const [_req, options] = this.buildRequest(route, opts);
375
+ const maxAttempts = (options.retries || 0) + 1;
376
+ let attempt = 0;
377
+ while (attempt < maxAttempts) {
378
+ attempt++;
379
+ const [req] = this.buildRequest(route, opts);
380
+ const res = await fetch(req).then((r) => {
381
+ if (!r.ok) throw new Error(r.statusText);
382
+ return r;
383
+ }).catch(async (error) => {
384
+ if (attempt < maxAttempts) {
385
+ const wait = attempt * 3e3;
386
+ console.warn(`${req.method} ${req.url} (attempt ${attempt} of ${maxAttempts})`, error);
387
+ await new Promise((resolve) => setTimeout(resolve, wait));
388
+ } else throw new Error(error);
389
+ });
390
+ if (res) return [res, req];
391
+ }
392
+ throw new Error(`Failed to fetch ${_req.url}`);
393
+ }
394
+ async fetchText(route, opts = {}) {
395
+ return this.fetch(route, opts).then(async ([res, req]) => {
396
+ return [
397
+ await res.text(),
398
+ res,
399
+ req
400
+ ];
401
+ });
402
+ }
403
+ async fetchJson(route, opts = {}) {
404
+ return this.fetchText(route, opts).then(([txt, res, req]) => [
405
+ JSON.parse(txt),
406
+ res,
407
+ req
408
+ ]);
409
+ }
410
+ };
411
+
412
+ //#endregion
413
+ //#region src/Log.ts
414
+ var Log = class {
415
+ static isTest = process.env.npm_package_name === "@brianbuie/node-kit" && process.env.npm_lifecycle_event === "test";
416
+ /**
417
+ * Gcloud parses JSON in stdout
418
+ */
419
+ static #toGcloud(entry) {
420
+ if (entry.details?.length === 1) console.log(JSON.stringify({
421
+ ...entry,
422
+ details: entry.details[0]
423
+ }));
424
+ else console.log(JSON.stringify(entry));
425
+ }
426
+ /**
427
+ * Includes colors and better inspection for logging during dev
428
+ */
429
+ static #toConsole(entry, color) {
430
+ if (entry.message) console.log(color(`[${entry.severity}] ${entry.message}`));
431
+ entry.details?.forEach((detail) => {
432
+ console.log(inspect(detail, {
433
+ depth: 10,
434
+ breakLength: 100,
435
+ compact: true,
436
+ colors: true
437
+ }));
438
+ });
439
+ }
440
+ static #log(options, ...input) {
441
+ const { message, details } = this.prepare(...input);
442
+ if (process.env.K_SERVICE !== void 0 || process.env.CLOUD_RUN_JOB !== void 0) {
443
+ this.#toGcloud({
444
+ message,
445
+ severity: options.severity,
446
+ details
447
+ });
448
+ return {
449
+ message,
450
+ details,
451
+ options
452
+ };
453
+ }
454
+ if (!this.isTest) this.#toConsole({
455
+ message,
456
+ severity: options.severity,
457
+ details
458
+ }, options.color);
459
+ return {
460
+ message,
461
+ details,
462
+ options
463
+ };
464
+ }
465
+ /**
466
+ * Handle first argument being a string or an object with a 'message' prop
467
+ * Also snapshots special objects (eg Error, Response) to keep props in later JSON.stringify output
468
+ */
469
+ static prepare(...input) {
470
+ let [first, ...rest] = input.map((i) => snapshot(i));
471
+ if (typeof first === "string") return {
472
+ message: first,
473
+ details: rest
474
+ };
475
+ if (isObjectLike(first) && typeof first["message"] === "string") {
476
+ const { message, ...firstDetails } = first;
477
+ return {
478
+ message,
479
+ details: [firstDetails, ...rest]
480
+ };
481
+ }
482
+ return { details: input };
483
+ }
484
+ /**
485
+ * Logs error details before throwing
486
+ */
487
+ static error(...input) {
488
+ const { message } = this.#log({
489
+ severity: "ERROR",
490
+ color: chalk.red
491
+ }, ...input);
492
+ throw new Error(message);
493
+ }
494
+ static warn(...input) {
495
+ return this.#log({
496
+ severity: "WARNING",
497
+ color: chalk.yellow
498
+ }, ...input);
499
+ }
500
+ static notice(...input) {
501
+ return this.#log({
502
+ severity: "NOTICE",
503
+ color: chalk.cyan
504
+ }, ...input);
505
+ }
506
+ static info(...input) {
507
+ return this.#log({
508
+ severity: "INFO",
509
+ color: chalk.white
510
+ }, ...input);
511
+ }
512
+ static debug(...input) {
513
+ if (process.argv.some((arg) => arg.includes("--debug")) || process.env.DEBUG !== void 0 || process.env.NODE_ENV !== "production") return this.#log({
514
+ severity: "DEBUG",
515
+ color: chalk.gray
516
+ }, ...input);
517
+ }
518
+ };
519
+
520
+ //#endregion
521
+ //#region src/timeout.ts
522
+ async function timeout(ms) {
523
+ return new Promise((resolve) => {
524
+ setTimeout(resolve, ms);
525
+ });
526
+ }
527
+
528
+ //#endregion
529
+ //#region src/TypeWriter.ts
530
+ var TypeWriter = class {
531
+ moduleName;
532
+ input = qt.jsonInputForTargetLanguage("typescript");
533
+ outDir;
534
+ qtSettings;
535
+ constructor(moduleName, settings = {}) {
536
+ this.moduleName = moduleName;
537
+ const { outDir, ...qtSettings } = settings;
538
+ this.outDir = outDir || "./types";
539
+ this.qtSettings = merge({
540
+ lang: "typescript",
541
+ rendererOptions: {
542
+ "just-types": true,
543
+ "prefer-types": true
544
+ },
545
+ inferEnums: false,
546
+ inferDateTimes: false
547
+ }, qtSettings);
548
+ }
549
+ async addMember(name, _samples) {
550
+ const samples = _samples.map((s) => typeof s === "string" ? s : JSON.stringify(s));
551
+ await this.input.addSource({
552
+ name,
553
+ samples
554
+ });
555
+ }
556
+ async toString() {
557
+ const inputData = new qt.InputData();
558
+ inputData.addInput(this.input);
559
+ return (await qt.quicktype({
560
+ inputData,
561
+ ...this.qtSettings
562
+ })).lines.join("\n");
563
+ }
564
+ async toFile() {
565
+ const result = await this.toString();
566
+ fs.mkdirSync(this.outDir, { recursive: true });
567
+ fs.writeFileSync(`${this.outDir}/${this.moduleName}.d.ts`, result);
568
+ }
569
+ };
570
+
571
+ //#endregion
572
+ export { Cache, Dir, Fetcher, File, FileType, FileTypeCsv, FileTypeJson, FileTypeNdjson, Log, TempDir, TypeWriter, snapshot, temp, timeout };
573
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","names":["output: Record<string, any>","obj: Record<string, any>","parsed: Row[]","#parseVal","params: [string, string][]","timeout","#toGcloud","#toConsole","#log"],"sources":["../src/snapshot.ts","../src/File.ts","../src/Dir.ts","../src/Cache.ts","../src/Fetcher.ts","../src/Log.ts","../src/timeout.ts","../src/TypeWriter.ts"],"sourcesContent":["import { isObjectLike } from 'lodash-es';\n\n/**\n * Allows special objects (Error, Headers, Set) to be included in JSON.stringify output\n * functions are removed\n */\nexport function snapshot(i: unknown, max = 50, depth = 0): any {\n if (Array.isArray(i)) {\n if (depth === max) return [];\n return i.map((c) => snapshot(c, max, depth + 1));\n }\n if (typeof i === 'function') return undefined;\n if (!isObjectLike(i)) return i;\n\n if (depth === max) return {};\n let output: Record<string, any> = {};\n // @ts-ignore If it has an 'entries' function, use that for looping (eg. Set, Map, Headers)\n if (typeof i.entries === 'function') {\n // @ts-ignore\n for (let [k, v] of i.entries()) {\n output[k] = snapshot(v, max, depth + 1);\n }\n return output;\n }\n\n // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Enumerability_and_ownership_of_properties\n\n // Get Enumerable, inherited properties\n const obj: Record<string, any> = i!;\n for (let key in obj) {\n output[key] = snapshot(obj[key], max, depth + 1);\n }\n\n // Get Non-enumberable, own properties\n Object.getOwnPropertyNames(obj).forEach((key) => {\n output[key] = snapshot(obj[key], max, depth + 1);\n });\n\n return output;\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport { Readable } from 'node:stream';\nimport { finished } from 'node:stream/promises';\nimport { writeToStream, parseStream } from 'fast-csv';\nimport { snapshot } from './snapshot.ts';\n\n/**\n * WARNING: API will change!\n */\nexport class File {\n path;\n root;\n dir;\n base;\n ext;\n name;\n\n constructor(filepath: string) {\n this.path = filepath;\n const { root, dir, base, ext, name } = path.parse(filepath);\n this.root = root;\n this.dir = dir;\n this.base = base;\n this.ext = ext;\n this.name = name;\n }\n\n get exists() {\n return fs.existsSync(this.path);\n }\n\n delete() {\n fs.rmSync(this.path, { force: true });\n }\n\n read() {\n return this.exists ? fs.readFileSync(this.path, 'utf8') : undefined;\n }\n\n /**\n * @returns lines as strings, removes trailing '\\n'\n */\n lines() {\n const contents = (this.read() || '').split('\\n');\n return contents.slice(0, contents.length - 1);\n }\n\n get readStream() {\n return this.exists ? fs.createReadStream(this.path) : Readable.from([]);\n }\n\n get writeStream() {\n fs.mkdirSync(path.parse(this.path).dir, { recursive: true });\n return fs.createWriteStream(this.path);\n }\n\n write(contents: string | ReadableStream) {\n fs.mkdirSync(path.parse(this.path).dir, { recursive: true });\n if (typeof contents === 'string') return fs.writeFileSync(this.path, contents);\n if (contents instanceof ReadableStream) return finished(Readable.from(contents).pipe(this.writeStream));\n throw new Error(`Invalid content type: ${typeof contents}`);\n }\n\n /**\n * creates file if it doesn't exist, appends string or array of strings as new lines.\n * File always ends with '\\n', so contents don't need to be read before appending\n */\n append(lines: string | string[]) {\n if (!this.exists) this.write('');\n const contents = Array.isArray(lines) ? lines.join('\\n') : lines;\n fs.appendFileSync(this.path, contents + '\\n');\n }\n\n static get FileType() {\n return FileType;\n }\n\n json<T>(contents?: T) {\n return new FileTypeJson<T>(this.path, contents);\n }\n\n static get json() {\n return FileTypeJson;\n }\n\n ndjson<T extends object>(lines?: T | T[]) {\n return new FileTypeNdjson<T>(this.path, lines);\n }\n\n static get ndjson() {\n return FileTypeNdjson;\n }\n\n async csv<T extends object>(rows?: T[], keys?: (keyof T)[]) {\n const csvFile = new FileTypeCsv<T>(this.path);\n if (rows) await csvFile.write(rows, keys);\n return csvFile;\n }\n\n static get csv() {\n return FileTypeCsv;\n }\n}\n\n/**\n * A generic file adaptor, extended by specific file type implementations\n */\nexport class FileType {\n file;\n\n constructor(filepath: string, contents?: string) {\n this.file = new File(filepath);\n if (contents) this.file.write(contents);\n }\n\n get exists() {\n return this.file.exists;\n }\n\n get path() {\n return this.file.path;\n }\n\n delete() {\n this.file.delete();\n }\n}\n\n/**\n * A .json file that maintains data type when reading/writing.\n * This is unsafe! Type is not checked at runtime, avoid using on files manipulated outside of your application.\n */\nexport class FileTypeJson<T> extends FileType {\n constructor(filepath: string, contents?: T) {\n super(filepath.endsWith('.json') ? filepath : filepath + '.json');\n if (contents) this.write(contents);\n }\n\n read() {\n const contents = this.file.read();\n return contents ? (JSON.parse(contents) as T) : undefined;\n }\n\n write(contents: T) {\n this.file.write(JSON.stringify(snapshot(contents), null, 2));\n }\n}\n\n/**\n * New-line delimited json file (.ndjson)\n * @see https://jsonltools.com/ndjson-format-specification\n */\nexport class FileTypeNdjson<T extends object> extends FileType {\n constructor(filepath: string, lines?: T | T[]) {\n super(filepath.endsWith('.ndjson') ? filepath : filepath + '.ndjson');\n if (lines) this.append(lines);\n }\n\n append(lines: T | T[]) {\n this.file.append(\n Array.isArray(lines) ? lines.map((l) => JSON.stringify(snapshot(l))) : JSON.stringify(snapshot(lines)),\n );\n }\n\n lines() {\n return this.file.lines().map((l) => JSON.parse(l) as T);\n }\n}\n\ntype Key<T extends object> = keyof T;\n\n/**\n * Comma separated values (.csv).\n * Input rows as objects, keys are used as column headers\n */\nexport class FileTypeCsv<Row extends object> extends FileType {\n constructor(filepath: string) {\n super(filepath.endsWith('.csv') ? filepath : filepath + '.csv');\n }\n\n async write(rows: Row[], keys?: Key<Row>[]) {\n const headerSet = new Set<Key<Row>>();\n if (keys) {\n for (const key of keys) headerSet.add(key);\n } else {\n for (const row of rows) {\n for (const key in row) headerSet.add(key);\n }\n }\n const headers = Array.from(headerSet);\n const outRows = rows.map((row) => headers.map((key) => row[key]));\n return finished(writeToStream(this.file.writeStream, [headers, ...outRows]));\n }\n\n #parseVal(val: string) {\n if (val.toLowerCase() === 'false') return false;\n if (val.toLowerCase() === 'true') return true;\n if (val.length === 0) return null;\n if (/^[\\.0-9]+$/.test(val)) return Number(val);\n return val;\n }\n\n async read() {\n return new Promise<Row[]>((resolve, reject) => {\n const parsed: Row[] = [];\n parseStream(this.file.readStream, { headers: true })\n .on('error', (e) => reject(e))\n .on('data', (raw: Record<Key<Row>, string>) => {\n parsed.push(\n Object.entries(raw).reduce(\n (all, [key, val]) => ({\n ...all,\n [key]: this.#parseVal(val as string),\n }),\n {} as Row,\n ),\n );\n })\n .on('end', () => resolve(parsed));\n });\n }\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport sanitizeFilename from 'sanitize-filename';\nimport { File } from './File.ts';\n\n/**\n * Reference to a specific directory with helpful methods for resolving filepaths,\n * sanitizing filenames, and saving files.\n */\nexport class Dir {\n path;\n\n /**\n * @param path can be relative to workspace or absolute\n */\n constructor(_path = './') {\n this.path = path.resolve(_path);\n }\n\n create() {\n fs.mkdirSync(this.path, { recursive: true });\n }\n\n /**\n * Create a new Dir inside the current Dir\n * @param subPath to create in current Dir\n * @example\n * const folder = new Dir('example');\n * // folder.path = './example'\n * const child = folder.dir('path/to/dir');\n * // child.path = './example/path/to/dir'\n */\n dir(subPath: string) {\n return new Dir(path.resolve(this.path, subPath));\n }\n\n tempDir(subPath: string) {\n return new TempDir(path.resolve(this.path, subPath));\n }\n\n sanitize(name: string) {\n return sanitizeFilename(name.replace('https://', '').replace('www.', ''), { replacement: '_' }).slice(-200);\n }\n\n /**\n * @param base - The file name with extension\n * @example\n * const folder = new Dir('example');\n * const filepath = folder.resolve('file.json');\n * // 'example/file.json'\n */\n filepath(base: string) {\n return path.resolve(this.path, this.sanitize(base));\n }\n\n file(base: string) {\n return new File(this.filepath(base));\n }\n}\n\n/**\n * Extends Dir class with method to `clear()` contents\n */\nexport class TempDir extends Dir {\n clear() {\n fs.rmSync(this.path, { recursive: true, force: true });\n this.create();\n }\n}\n\n/**\n * Common temp dir location\n */\nexport const temp = new TempDir('.temp');\n","import { type Duration, isAfter, add } from 'date-fns';\nimport { temp } from './Dir.ts';\n\nconst cacheDir = temp.dir('cache');\n\n/**\n * Save data to a local file with an expiration.\n * Fresh/stale data is returned with a flag for if it's fresh or not,\n * so stale data can still be used if needed.\n */\nexport class Cache<T> {\n file;\n ttl;\n\n constructor(key: string, ttl: number | Duration, initialData?: T) {\n this.file = cacheDir.file(key).json<{ savedAt: string; data: T }>();\n this.ttl = typeof ttl === 'number' ? { minutes: ttl } : ttl;\n if (initialData) this.write(initialData);\n }\n\n write(data: T) {\n this.file.write({ savedAt: new Date().toUTCString(), data });\n }\n\n read(): [T | undefined, boolean] {\n const { savedAt, data } = this.file.read() || {};\n const isFresh = Boolean(savedAt && isAfter(add(savedAt, this.ttl), new Date()));\n return [data, isFresh];\n }\n}\n","import { merge } from 'lodash-es';\nimport extractDomain from 'extract-domain';\n\nexport type Route = string | URL;\n\ntype QueryVal = string | number | boolean | null | undefined;\nexport type Query = Record<string, QueryVal | QueryVal[]>;\n\nexport type FetchOptions = RequestInit & {\n base?: string;\n query?: Query;\n headers?: Record<string, string>;\n data?: any;\n timeout?: number;\n retries?: number;\n retryDelay?: number;\n};\n\n/**\n * Fetcher provides a quick way to set up a basic API connection\n * with options applied to every request.\n * Includes basic methods for requesting and parsing responses\n */\nexport class Fetcher {\n defaultOptions;\n\n constructor(opts: FetchOptions = {}) {\n this.defaultOptions = {\n timeout: 60000,\n retries: 0,\n retryDelay: 3000,\n ...opts,\n };\n }\n\n /**\n * Build URL with URLSearchParams if query is provided.\n * Also returns domain, to help with cookies\n */\n buildUrl(route: Route, opts: FetchOptions = {}): [URL, string] {\n const mergedOptions = merge({}, this.defaultOptions, opts);\n const params: [string, string][] = [];\n Object.entries(mergedOptions.query || {}).forEach(([key, val]) => {\n if (val === undefined) return;\n if (Array.isArray(val)) {\n val.forEach((v) => {\n params.push([key, `${v}`]);\n });\n } else {\n params.push([key, `${val}`]);\n }\n });\n const search = params.length > 0 ? '?' + new URLSearchParams(params).toString() : '';\n const url = new URL(route + search, this.defaultOptions.base);\n const domain = extractDomain(url.href) as string;\n return [url, domain];\n }\n\n /**\n * Merges options to get headers. Useful when extending the Fetcher class to add custom auth.\n */\n buildHeaders(route: Route, opts: FetchOptions = {}) {\n const { headers } = merge({}, this.defaultOptions, opts);\n return headers || {};\n }\n\n /**\n * Builds request, merging defaultOptions and provided options.\n * Includes Abort signal for timeout\n */\n buildRequest(route: Route, opts: FetchOptions = {}): [Request, FetchOptions, string] {\n const mergedOptions = merge({}, this.defaultOptions, opts);\n const { query, data, timeout, retries, ...init } = mergedOptions;\n init.headers = this.buildHeaders(route, mergedOptions);\n if (data) {\n init.headers['content-type'] = init.headers['content-type'] || 'application/json';\n init.method = init.method || 'POST';\n init.body = JSON.stringify(data);\n }\n if (timeout) {\n init.signal = AbortSignal.timeout(timeout);\n }\n const [url, domain] = this.buildUrl(route, mergedOptions);\n const req = new Request(url, init);\n return [req, mergedOptions, domain];\n }\n\n /**\n * Builds and performs the request, merging provided options with defaultOptions.\n * If `opts.data` is provided, method is updated to POST, content-type json, data is stringified in the body.\n * Retries on local or network error, with increasing backoff.\n */\n async fetch(route: Route, opts: FetchOptions = {}): Promise<[Response, Request]> {\n const [_req, options] = this.buildRequest(route, opts);\n const maxAttempts = (options.retries || 0) + 1;\n let attempt = 0;\n while (attempt < maxAttempts) {\n attempt++;\n const [req] = this.buildRequest(route, opts);\n const res = await fetch(req)\n .then((r) => {\n if (!r.ok) throw new Error(r.statusText);\n return r;\n })\n .catch(async (error) => {\n if (attempt < maxAttempts) {\n const wait = attempt * 3000;\n console.warn(`${req.method} ${req.url} (attempt ${attempt} of ${maxAttempts})`, error);\n await new Promise((resolve) => setTimeout(resolve, wait));\n } else {\n throw new Error(error);\n }\n });\n if (res) return [res, req];\n }\n throw new Error(`Failed to fetch ${_req.url}`);\n }\n\n async fetchText(route: Route, opts: FetchOptions = {}): Promise<[string, Response, Request]> {\n return this.fetch(route, opts).then(async ([res, req]) => {\n const text = await res.text();\n return [text, res, req];\n });\n }\n\n async fetchJson<T>(route: Route, opts: FetchOptions = {}): Promise<[T, Response, Request]> {\n return this.fetchText(route, opts).then(([txt, res, req]) => [JSON.parse(txt) as T, res, req]);\n }\n}\n","import { inspect } from 'node:util';\nimport { isObjectLike } from 'lodash-es';\nimport chalk, { type ChalkInstance } from 'chalk';\nimport { snapshot } from './snapshot.ts';\n\ntype Severity = 'DEFAULT' | 'DEBUG' | 'INFO' | 'NOTICE' | 'WARNING' | 'ERROR' | 'CRITICAL' | 'ALERT' | 'EMERGENCY';\n\ntype Options = {\n severity: Severity;\n color: ChalkInstance;\n};\n\ntype Entry = {\n message?: string;\n severity: Severity;\n details?: unknown[];\n};\n\nexport class Log {\n // Only silence logs when THIS package is running its own tests\n static isTest = process.env.npm_package_name === '@brianbuie/node-kit' && process.env.npm_lifecycle_event === 'test';\n\n /**\n * Gcloud parses JSON in stdout\n */\n static #toGcloud(entry: Entry) {\n if (entry.details?.length === 1) {\n console.log(JSON.stringify({ ...entry, details: entry.details[0] }));\n } else {\n console.log(JSON.stringify(entry));\n }\n }\n\n /**\n * Includes colors and better inspection for logging during dev\n */\n static #toConsole(entry: Entry, color: ChalkInstance) {\n if (entry.message) console.log(color(`[${entry.severity}] ${entry.message}`));\n entry.details?.forEach((detail) => {\n console.log(inspect(detail, { depth: 10, breakLength: 100, compact: true, colors: true }));\n });\n }\n\n static #log(options: Options, ...input: unknown[]) {\n const { message, details } = this.prepare(...input);\n // https://cloud.google.com/run/docs/container-contract#env-vars\n const isGcloud = process.env.K_SERVICE !== undefined || process.env.CLOUD_RUN_JOB !== undefined;\n if (isGcloud) {\n this.#toGcloud({ message, severity: options.severity, details });\n return { message, details, options };\n }\n // Hide output while testing this package\n if (!this.isTest) {\n this.#toConsole({ message, severity: options.severity, details }, options.color);\n }\n return { message, details, options };\n }\n\n /**\n * Handle first argument being a string or an object with a 'message' prop\n * Also snapshots special objects (eg Error, Response) to keep props in later JSON.stringify output\n */\n static prepare(...input: unknown[]): { message?: string; details: unknown[] } {\n let [first, ...rest] = input.map((i) => snapshot(i));\n if (typeof first === 'string') return { message: first, details: rest };\n // @ts-ignore\n if (isObjectLike(first) && typeof first['message'] === 'string') {\n const { message, ...firstDetails } = first as { message: string };\n return { message, details: [firstDetails, ...rest] };\n }\n return { details: input };\n }\n\n /**\n * Logs error details before throwing\n */\n static error(...input: unknown[]) {\n const { message } = this.#log({ severity: 'ERROR', color: chalk.red }, ...input);\n throw new Error(message);\n }\n\n static warn(...input: unknown[]) {\n return this.#log({ severity: 'WARNING', color: chalk.yellow }, ...input);\n }\n\n static notice(...input: unknown[]) {\n return this.#log({ severity: 'NOTICE', color: chalk.cyan }, ...input);\n }\n\n static info(...input: unknown[]) {\n return this.#log({ severity: 'INFO', color: chalk.white }, ...input);\n }\n\n static debug(...input: unknown[]) {\n const debugging = process.argv.some((arg) => arg.includes('--debug')) || process.env.DEBUG !== undefined;\n if (debugging || process.env.NODE_ENV !== 'production') {\n return this.#log({ severity: 'DEBUG', color: chalk.gray }, ...input);\n }\n }\n}\n","export async function timeout(ms: number) {\n return new Promise((resolve) => {\n setTimeout(resolve, ms);\n });\n}\n","import * as fs from 'node:fs';\nimport { merge } from 'lodash-es';\nimport * as qt from 'quicktype-core';\n\nexport class TypeWriter {\n moduleName;\n input = qt.jsonInputForTargetLanguage('typescript');\n outDir;\n qtSettings;\n\n constructor(moduleName: string, settings: { outDir?: string } & Partial<qt.Options> = {}) {\n this.moduleName = moduleName;\n const { outDir, ...qtSettings } = settings;\n this.outDir = outDir || './types';\n const defaultSettings = {\n lang: 'typescript',\n rendererOptions: {\n 'just-types': true,\n 'prefer-types': true,\n },\n inferEnums: false,\n inferDateTimes: false,\n };\n this.qtSettings = merge(defaultSettings, qtSettings);\n }\n\n async addMember(name: string, _samples: any[]) {\n const samples = _samples.map((s) => (typeof s === 'string' ? s : JSON.stringify(s)));\n await this.input.addSource({ name, samples });\n }\n\n async toString() {\n const inputData = new qt.InputData();\n inputData.addInput(this.input);\n const result = await qt.quicktype({\n inputData,\n ...this.qtSettings,\n });\n return result.lines.join('\\n');\n }\n\n async toFile() {\n const result = await this.toString();\n fs.mkdirSync(this.outDir, { recursive: true });\n fs.writeFileSync(`${this.outDir}/${this.moduleName}.d.ts`, result);\n }\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brianbuie/node-kit",
3
- "version": "0.9.1",
3
+ "version": "0.10.0",
4
4
  "license": "ISC",
5
5
  "repository": {
6
6
  "type": "git",
@@ -28,6 +28,8 @@
28
28
  "node": ">=24"
29
29
  },
30
30
  "dependencies": {
31
+ "@types/lodash-es": "^4.17.12",
32
+ "@types/node": "^24.9.1",
31
33
  "chalk": "^5.6.2",
32
34
  "date-fns": "^4.1.0",
33
35
  "extract-domain": "^5.0.2",
@@ -37,8 +39,6 @@
37
39
  "sanitize-filename": "^1.6.3"
38
40
  },
39
41
  "devDependencies": {
40
- "@types/lodash-es": "^4.17.12",
41
- "@types/node": "^24.9.1",
42
42
  "ts2md": "^0.2.8",
43
43
  "tsdown": "^0.16.6",
44
44
  "typescript": "^5.9.3"