@brianbuie/node-kit 0.9.0 → 0.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +15 -0
- package/package.json +7 -7
- package/src/Cache.ts +1 -1
- package/src/Dir.test.ts +1 -1
- package/src/Dir.ts +1 -1
- package/src/Fetcher.test.ts +1 -1
- package/src/File.test.ts +2 -2
- package/src/File.ts +1 -1
- package/src/Log.test.ts +1 -1
- package/src/Log.ts +1 -1
- package/src/TypeWriter.test.ts +1 -1
- package/src/index.ts +8 -8
- package/src/snapshot.test.ts +2 -2
- package/src/timeout.test.ts +1 -1
- package/dist/Cache.d.ts +0 -16
- package/dist/Cache.js +0 -26
- package/dist/Dir.d.ts +0 -44
- package/dist/Dir.js +0 -64
- package/dist/Fetcher.d.ts +0 -65
- package/dist/Fetcher.js +0 -111
- package/dist/File.d.ts +0 -71
- package/dist/File.js +0 -185
- package/dist/Log.d.ts +0 -43
- package/dist/Log.js +0 -80
- package/dist/TypeWriter.d.ts +0 -452
- package/dist/TypeWriter.js +0 -42
- package/dist/index.d.ts +0 -8
- package/dist/index.js +0 -8
- package/dist/snapshot.d.ts +0 -5
- package/dist/snapshot.js +0 -38
- package/dist/timeout.d.ts +0 -1
- package/dist/timeout.js +0 -5
package/LICENSE
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
ISC License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Brian Buie
|
|
4
|
+
|
|
5
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
6
|
+
purpose with or without fee is hereby granted, provided that the above
|
|
7
|
+
copyright notice and this permission notice appear in all copies.
|
|
8
|
+
|
|
9
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
10
|
+
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
11
|
+
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
12
|
+
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
13
|
+
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
14
|
+
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
15
|
+
PERFORMANCE OF THIS SOFTWARE.
|
package/package.json
CHANGED
|
@@ -1,28 +1,27 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@brianbuie/node-kit",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.1",
|
|
4
4
|
"license": "ISC",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
7
7
|
"url": "git+https://github.com/brianbuie/node-kit.git"
|
|
8
8
|
},
|
|
9
9
|
"scripts": {
|
|
10
|
-
"
|
|
11
|
-
"test": "tsc && node --test \"
|
|
12
|
-
"preversion": "npm test && npm run
|
|
10
|
+
"build": "tsdown && node ./node_modules/ts2md/out/src/ts2md.js --firstHeadingLevel=1",
|
|
11
|
+
"test": "tsc && node --test \"src/*.test.ts\" --quiet",
|
|
12
|
+
"preversion": "npm test && npm run build",
|
|
13
13
|
"postversion": "git push --follow-tags"
|
|
14
14
|
},
|
|
15
15
|
"type": "module",
|
|
16
16
|
"exports": {
|
|
17
17
|
".": {
|
|
18
|
-
"
|
|
19
|
-
"
|
|
18
|
+
"default": "./dist/index.mjs",
|
|
19
|
+
"types": "./dist/index.d.mts"
|
|
20
20
|
}
|
|
21
21
|
},
|
|
22
22
|
"files": [
|
|
23
23
|
"src",
|
|
24
24
|
"dist",
|
|
25
|
-
"!dist/**/*.test.*",
|
|
26
25
|
"README.md"
|
|
27
26
|
],
|
|
28
27
|
"engines": {
|
|
@@ -41,6 +40,7 @@
|
|
|
41
40
|
"@types/lodash-es": "^4.17.12",
|
|
42
41
|
"@types/node": "^24.9.1",
|
|
43
42
|
"ts2md": "^0.2.8",
|
|
43
|
+
"tsdown": "^0.16.6",
|
|
44
44
|
"typescript": "^5.9.3"
|
|
45
45
|
}
|
|
46
46
|
}
|
package/src/Cache.ts
CHANGED
package/src/Dir.test.ts
CHANGED
package/src/Dir.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as fs from 'node:fs';
|
|
2
2
|
import * as path from 'node:path';
|
|
3
3
|
import sanitizeFilename from 'sanitize-filename';
|
|
4
|
-
import { File } from './File.
|
|
4
|
+
import { File } from './File.ts';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Reference to a specific directory with helpful methods for resolving filepaths,
|
package/src/Fetcher.test.ts
CHANGED
package/src/File.test.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { describe, it } from 'node:test';
|
|
2
2
|
import assert from 'node:assert';
|
|
3
|
-
import { temp } from './Dir.
|
|
4
|
-
import { File } from './File.
|
|
3
|
+
import { temp } from './Dir.ts';
|
|
4
|
+
import { File } from './File.ts';
|
|
5
5
|
|
|
6
6
|
const testDir = temp.dir('file-test');
|
|
7
7
|
testDir.clear();
|
package/src/File.ts
CHANGED
|
@@ -3,7 +3,7 @@ import * as path from 'node:path';
|
|
|
3
3
|
import { Readable } from 'node:stream';
|
|
4
4
|
import { finished } from 'node:stream/promises';
|
|
5
5
|
import { writeToStream, parseStream } from 'fast-csv';
|
|
6
|
-
import { snapshot } from './snapshot.
|
|
6
|
+
import { snapshot } from './snapshot.ts';
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* WARNING: API will change!
|
package/src/Log.test.ts
CHANGED
package/src/Log.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { inspect } from 'node:util';
|
|
2
2
|
import { isObjectLike } from 'lodash-es';
|
|
3
3
|
import chalk, { type ChalkInstance } from 'chalk';
|
|
4
|
-
import { snapshot } from './snapshot.
|
|
4
|
+
import { snapshot } from './snapshot.ts';
|
|
5
5
|
|
|
6
6
|
type Severity = 'DEFAULT' | 'DEBUG' | 'INFO' | 'NOTICE' | 'WARNING' | 'ERROR' | 'CRITICAL' | 'ALERT' | 'EMERGENCY';
|
|
7
7
|
|
package/src/TypeWriter.test.ts
CHANGED
package/src/index.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
export { Dir, TempDir, temp } from './Dir.
|
|
2
|
-
export { Cache } from './Cache.
|
|
3
|
-
export { Fetcher, type Route, type Query, type FetchOptions } from './Fetcher.
|
|
4
|
-
export { File, FileType, FileTypeJson, FileTypeNdjson, FileTypeCsv } from './File.
|
|
5
|
-
export { Log } from './Log.
|
|
6
|
-
export { snapshot } from './snapshot.
|
|
7
|
-
export { timeout } from './timeout.
|
|
8
|
-
export { TypeWriter } from './TypeWriter.
|
|
1
|
+
export { Dir, TempDir, temp } from './Dir.ts';
|
|
2
|
+
export { Cache } from './Cache.ts';
|
|
3
|
+
export { Fetcher, type Route, type Query, type FetchOptions } from './Fetcher.ts';
|
|
4
|
+
export { File, FileType, FileTypeJson, FileTypeNdjson, FileTypeCsv } from './File.ts';
|
|
5
|
+
export { Log } from './Log.ts';
|
|
6
|
+
export { snapshot } from './snapshot.ts';
|
|
7
|
+
export { timeout } from './timeout.ts';
|
|
8
|
+
export { TypeWriter } from './TypeWriter.ts';
|
package/src/snapshot.test.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { describe, it } from 'node:test';
|
|
2
2
|
import assert from 'node:assert';
|
|
3
|
-
import { snapshot } from './snapshot.
|
|
4
|
-
import { temp } from './Dir.
|
|
3
|
+
import { snapshot } from './snapshot.ts';
|
|
4
|
+
import { temp } from './Dir.ts';
|
|
5
5
|
|
|
6
6
|
describe('snapshot', () => {
|
|
7
7
|
it('Captures Error details', () => {
|
package/src/timeout.test.ts
CHANGED
package/dist/Cache.d.ts
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { type Duration } from 'date-fns';
|
|
2
|
-
/**
|
|
3
|
-
* Save data to a local file with an expiration.
|
|
4
|
-
* Fresh/stale data is returned with a flag for if it's fresh or not,
|
|
5
|
-
* so stale data can still be used if needed.
|
|
6
|
-
*/
|
|
7
|
-
export declare class Cache<T> {
|
|
8
|
-
file: import("./File.js").FileTypeJson<{
|
|
9
|
-
savedAt: string;
|
|
10
|
-
data: T;
|
|
11
|
-
}>;
|
|
12
|
-
ttl: Duration;
|
|
13
|
-
constructor(key: string, ttl: number | Duration, initialData?: T);
|
|
14
|
-
write(data: T): void;
|
|
15
|
-
read(): [T | undefined, boolean];
|
|
16
|
-
}
|
package/dist/Cache.js
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { isAfter, add } from 'date-fns';
|
|
2
|
-
import { temp } from './Dir.js';
|
|
3
|
-
const cacheDir = temp.dir('cache');
|
|
4
|
-
/**
|
|
5
|
-
* Save data to a local file with an expiration.
|
|
6
|
-
* Fresh/stale data is returned with a flag for if it's fresh or not,
|
|
7
|
-
* so stale data can still be used if needed.
|
|
8
|
-
*/
|
|
9
|
-
export class Cache {
|
|
10
|
-
file;
|
|
11
|
-
ttl;
|
|
12
|
-
constructor(key, ttl, initialData) {
|
|
13
|
-
this.file = cacheDir.file(key).json();
|
|
14
|
-
this.ttl = typeof ttl === 'number' ? { minutes: ttl } : ttl;
|
|
15
|
-
if (initialData)
|
|
16
|
-
this.write(initialData);
|
|
17
|
-
}
|
|
18
|
-
write(data) {
|
|
19
|
-
this.file.write({ savedAt: new Date().toUTCString(), data });
|
|
20
|
-
}
|
|
21
|
-
read() {
|
|
22
|
-
const { savedAt, data } = this.file.read() || {};
|
|
23
|
-
const isFresh = Boolean(savedAt && isAfter(add(savedAt, this.ttl), new Date()));
|
|
24
|
-
return [data, isFresh];
|
|
25
|
-
}
|
|
26
|
-
}
|
package/dist/Dir.d.ts
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import { File } from './File.js';
|
|
2
|
-
/**
|
|
3
|
-
* Reference to a specific directory with helpful methods for resolving filepaths,
|
|
4
|
-
* sanitizing filenames, and saving files.
|
|
5
|
-
*/
|
|
6
|
-
export declare class Dir {
|
|
7
|
-
path: string;
|
|
8
|
-
/**
|
|
9
|
-
* @param path can be relative to workspace or absolute
|
|
10
|
-
*/
|
|
11
|
-
constructor(_path: string);
|
|
12
|
-
create(): void;
|
|
13
|
-
/**
|
|
14
|
-
* Create a new Dir inside the current Dir
|
|
15
|
-
* @param subPath to create in current Dir
|
|
16
|
-
* @example
|
|
17
|
-
* const folder = new Dir('example');
|
|
18
|
-
* // folder.path = './example'
|
|
19
|
-
* const child = folder.subDir('path/to/dir');
|
|
20
|
-
* // child.path = './example/path/to/dir'
|
|
21
|
-
*/
|
|
22
|
-
dir(subPath: string): Dir;
|
|
23
|
-
sanitize(name: string): string;
|
|
24
|
-
/**
|
|
25
|
-
* @param base - The file name with extension
|
|
26
|
-
* @example
|
|
27
|
-
* const folder = new Dir('example');
|
|
28
|
-
* const filepath = folder.resolve('file.json');
|
|
29
|
-
* // 'example/file.json'
|
|
30
|
-
*/
|
|
31
|
-
filepath(base: string): string;
|
|
32
|
-
file(base: string): File;
|
|
33
|
-
}
|
|
34
|
-
/**
|
|
35
|
-
* Extends Dir class with method to `clear()` contents
|
|
36
|
-
*/
|
|
37
|
-
export declare class TempDir extends Dir {
|
|
38
|
-
dir(subPath: string): TempDir;
|
|
39
|
-
clear(): void;
|
|
40
|
-
}
|
|
41
|
-
/**
|
|
42
|
-
* Common temp dir location
|
|
43
|
-
*/
|
|
44
|
-
export declare const temp: TempDir;
|
package/dist/Dir.js
DELETED
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
import * as fs from 'node:fs';
|
|
2
|
-
import * as path from 'node:path';
|
|
3
|
-
import sanitizeFilename from 'sanitize-filename';
|
|
4
|
-
import { File } from './File.js';
|
|
5
|
-
/**
|
|
6
|
-
* Reference to a specific directory with helpful methods for resolving filepaths,
|
|
7
|
-
* sanitizing filenames, and saving files.
|
|
8
|
-
*/
|
|
9
|
-
export class Dir {
|
|
10
|
-
path;
|
|
11
|
-
/**
|
|
12
|
-
* @param path can be relative to workspace or absolute
|
|
13
|
-
*/
|
|
14
|
-
constructor(_path) {
|
|
15
|
-
this.path = _path;
|
|
16
|
-
}
|
|
17
|
-
create() {
|
|
18
|
-
fs.mkdirSync(this.path, { recursive: true });
|
|
19
|
-
}
|
|
20
|
-
/**
|
|
21
|
-
* Create a new Dir inside the current Dir
|
|
22
|
-
* @param subPath to create in current Dir
|
|
23
|
-
* @example
|
|
24
|
-
* const folder = new Dir('example');
|
|
25
|
-
* // folder.path = './example'
|
|
26
|
-
* const child = folder.subDir('path/to/dir');
|
|
27
|
-
* // child.path = './example/path/to/dir'
|
|
28
|
-
*/
|
|
29
|
-
dir(subPath) {
|
|
30
|
-
return new Dir(path.resolve(this.path, subPath));
|
|
31
|
-
}
|
|
32
|
-
sanitize(name) {
|
|
33
|
-
return sanitizeFilename(name.replace('https://', '').replace('www.', ''), { replacement: '_' }).slice(-200);
|
|
34
|
-
}
|
|
35
|
-
/**
|
|
36
|
-
* @param base - The file name with extension
|
|
37
|
-
* @example
|
|
38
|
-
* const folder = new Dir('example');
|
|
39
|
-
* const filepath = folder.resolve('file.json');
|
|
40
|
-
* // 'example/file.json'
|
|
41
|
-
*/
|
|
42
|
-
filepath(base) {
|
|
43
|
-
return path.resolve(this.path, this.sanitize(base));
|
|
44
|
-
}
|
|
45
|
-
file(base) {
|
|
46
|
-
return new File(this.filepath(base));
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
/**
|
|
50
|
-
* Extends Dir class with method to `clear()` contents
|
|
51
|
-
*/
|
|
52
|
-
export class TempDir extends Dir {
|
|
53
|
-
dir(subPath) {
|
|
54
|
-
return new TempDir(path.resolve(this.path, subPath));
|
|
55
|
-
}
|
|
56
|
-
clear() {
|
|
57
|
-
fs.rmSync(this.path, { recursive: true, force: true });
|
|
58
|
-
this.create();
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
/**
|
|
62
|
-
* Common temp dir location
|
|
63
|
-
*/
|
|
64
|
-
export const temp = new TempDir('.temp');
|
package/dist/Fetcher.d.ts
DELETED
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
export type Route = string | URL;
|
|
2
|
-
type QueryVal = string | number | boolean | null | undefined;
|
|
3
|
-
export type Query = Record<string, QueryVal | QueryVal[]>;
|
|
4
|
-
export type FetchOptions = RequestInit & {
|
|
5
|
-
base?: string;
|
|
6
|
-
query?: Query;
|
|
7
|
-
headers?: Record<string, string>;
|
|
8
|
-
data?: any;
|
|
9
|
-
timeout?: number;
|
|
10
|
-
retries?: number;
|
|
11
|
-
retryDelay?: number;
|
|
12
|
-
};
|
|
13
|
-
/**
|
|
14
|
-
* Fetcher provides a quick way to set up a basic API connection
|
|
15
|
-
* with options applied to every request.
|
|
16
|
-
* Includes basic methods for requesting and parsing responses
|
|
17
|
-
*/
|
|
18
|
-
export declare class Fetcher {
|
|
19
|
-
defaultOptions: {
|
|
20
|
-
body?: BodyInit | null;
|
|
21
|
-
cache?: RequestCache;
|
|
22
|
-
credentials?: RequestCredentials;
|
|
23
|
-
headers?: (HeadersInit & Record<string, string>) | undefined;
|
|
24
|
-
integrity?: string;
|
|
25
|
-
keepalive?: boolean;
|
|
26
|
-
method?: string;
|
|
27
|
-
mode?: RequestMode;
|
|
28
|
-
priority?: RequestPriority;
|
|
29
|
-
redirect?: RequestRedirect;
|
|
30
|
-
referrer?: string;
|
|
31
|
-
referrerPolicy?: ReferrerPolicy;
|
|
32
|
-
signal?: AbortSignal | null;
|
|
33
|
-
window?: null;
|
|
34
|
-
base?: string;
|
|
35
|
-
query?: Query;
|
|
36
|
-
data?: any;
|
|
37
|
-
timeout: number;
|
|
38
|
-
retries: number;
|
|
39
|
-
retryDelay: number;
|
|
40
|
-
};
|
|
41
|
-
constructor(opts?: FetchOptions);
|
|
42
|
-
/**
|
|
43
|
-
* Build URL with URLSearchParams if query is provided.
|
|
44
|
-
* Also returns domain, to help with cookies
|
|
45
|
-
*/
|
|
46
|
-
buildUrl(route: Route, opts?: FetchOptions): [URL, string];
|
|
47
|
-
/**
|
|
48
|
-
* Merges options to get headers. Useful when extending the Fetcher class to add custom auth.
|
|
49
|
-
*/
|
|
50
|
-
buildHeaders(route: Route, opts?: FetchOptions): HeadersInit & Record<string, string>;
|
|
51
|
-
/**
|
|
52
|
-
* Builds request, merging defaultOptions and provided options.
|
|
53
|
-
* Includes Abort signal for timeout
|
|
54
|
-
*/
|
|
55
|
-
buildRequest(route: Route, opts?: FetchOptions): [Request, FetchOptions, string];
|
|
56
|
-
/**
|
|
57
|
-
* Builds and performs the request, merging provided options with defaultOptions.
|
|
58
|
-
* If `opts.data` is provided, method is updated to POST, content-type json, data is stringified in the body.
|
|
59
|
-
* Retries on local or network error, with increasing backoff.
|
|
60
|
-
*/
|
|
61
|
-
fetch(route: Route, opts?: FetchOptions): Promise<[Response, Request]>;
|
|
62
|
-
fetchText(route: Route, opts?: FetchOptions): Promise<[string, Response, Request]>;
|
|
63
|
-
fetchJson<T>(route: Route, opts?: FetchOptions): Promise<[T, Response, Request]>;
|
|
64
|
-
}
|
|
65
|
-
export {};
|
package/dist/Fetcher.js
DELETED
|
@@ -1,111 +0,0 @@
|
|
|
1
|
-
import { merge } from 'lodash-es';
|
|
2
|
-
import extractDomain from 'extract-domain';
|
|
3
|
-
/**
|
|
4
|
-
* Fetcher provides a quick way to set up a basic API connection
|
|
5
|
-
* with options applied to every request.
|
|
6
|
-
* Includes basic methods for requesting and parsing responses
|
|
7
|
-
*/
|
|
8
|
-
export class Fetcher {
|
|
9
|
-
defaultOptions;
|
|
10
|
-
constructor(opts = {}) {
|
|
11
|
-
this.defaultOptions = {
|
|
12
|
-
timeout: 60000,
|
|
13
|
-
retries: 0,
|
|
14
|
-
retryDelay: 3000,
|
|
15
|
-
...opts,
|
|
16
|
-
};
|
|
17
|
-
}
|
|
18
|
-
/**
|
|
19
|
-
* Build URL with URLSearchParams if query is provided.
|
|
20
|
-
* Also returns domain, to help with cookies
|
|
21
|
-
*/
|
|
22
|
-
buildUrl(route, opts = {}) {
|
|
23
|
-
const mergedOptions = merge({}, this.defaultOptions, opts);
|
|
24
|
-
const params = [];
|
|
25
|
-
Object.entries(mergedOptions.query || {}).forEach(([key, val]) => {
|
|
26
|
-
if (val === undefined)
|
|
27
|
-
return;
|
|
28
|
-
if (Array.isArray(val)) {
|
|
29
|
-
val.forEach((v) => {
|
|
30
|
-
params.push([key, `${v}`]);
|
|
31
|
-
});
|
|
32
|
-
}
|
|
33
|
-
else {
|
|
34
|
-
params.push([key, `${val}`]);
|
|
35
|
-
}
|
|
36
|
-
});
|
|
37
|
-
const search = params.length > 0 ? '?' + new URLSearchParams(params).toString() : '';
|
|
38
|
-
const url = new URL(route + search, this.defaultOptions.base);
|
|
39
|
-
const domain = extractDomain(url.href);
|
|
40
|
-
return [url, domain];
|
|
41
|
-
}
|
|
42
|
-
/**
|
|
43
|
-
* Merges options to get headers. Useful when extending the Fetcher class to add custom auth.
|
|
44
|
-
*/
|
|
45
|
-
buildHeaders(route, opts = {}) {
|
|
46
|
-
const { headers } = merge({}, this.defaultOptions, opts);
|
|
47
|
-
return headers || {};
|
|
48
|
-
}
|
|
49
|
-
/**
|
|
50
|
-
* Builds request, merging defaultOptions and provided options.
|
|
51
|
-
* Includes Abort signal for timeout
|
|
52
|
-
*/
|
|
53
|
-
buildRequest(route, opts = {}) {
|
|
54
|
-
const mergedOptions = merge({}, this.defaultOptions, opts);
|
|
55
|
-
const { query, data, timeout, retries, ...init } = mergedOptions;
|
|
56
|
-
init.headers = this.buildHeaders(route, mergedOptions);
|
|
57
|
-
if (data) {
|
|
58
|
-
init.headers['content-type'] = init.headers['content-type'] || 'application/json';
|
|
59
|
-
init.method = init.method || 'POST';
|
|
60
|
-
init.body = JSON.stringify(data);
|
|
61
|
-
}
|
|
62
|
-
if (timeout) {
|
|
63
|
-
init.signal = AbortSignal.timeout(timeout);
|
|
64
|
-
}
|
|
65
|
-
const [url, domain] = this.buildUrl(route, mergedOptions);
|
|
66
|
-
const req = new Request(url, init);
|
|
67
|
-
return [req, mergedOptions, domain];
|
|
68
|
-
}
|
|
69
|
-
/**
|
|
70
|
-
* Builds and performs the request, merging provided options with defaultOptions.
|
|
71
|
-
* If `opts.data` is provided, method is updated to POST, content-type json, data is stringified in the body.
|
|
72
|
-
* Retries on local or network error, with increasing backoff.
|
|
73
|
-
*/
|
|
74
|
-
async fetch(route, opts = {}) {
|
|
75
|
-
const [_req, options] = this.buildRequest(route, opts);
|
|
76
|
-
const maxAttempts = (options.retries || 0) + 1;
|
|
77
|
-
let attempt = 0;
|
|
78
|
-
while (attempt < maxAttempts) {
|
|
79
|
-
attempt++;
|
|
80
|
-
const [req] = this.buildRequest(route, opts);
|
|
81
|
-
const res = await fetch(req)
|
|
82
|
-
.then((r) => {
|
|
83
|
-
if (!r.ok)
|
|
84
|
-
throw new Error(r.statusText);
|
|
85
|
-
return r;
|
|
86
|
-
})
|
|
87
|
-
.catch(async (error) => {
|
|
88
|
-
if (attempt < maxAttempts) {
|
|
89
|
-
const wait = attempt * 3000;
|
|
90
|
-
console.warn(`${req.method} ${req.url} (attempt ${attempt} of ${maxAttempts})`, error);
|
|
91
|
-
await new Promise((resolve) => setTimeout(resolve, wait));
|
|
92
|
-
}
|
|
93
|
-
else {
|
|
94
|
-
throw new Error(error);
|
|
95
|
-
}
|
|
96
|
-
});
|
|
97
|
-
if (res)
|
|
98
|
-
return [res, req];
|
|
99
|
-
}
|
|
100
|
-
throw new Error(`Failed to fetch ${_req.url}`);
|
|
101
|
-
}
|
|
102
|
-
async fetchText(route, opts = {}) {
|
|
103
|
-
return this.fetch(route, opts).then(async ([res, req]) => {
|
|
104
|
-
const text = await res.text();
|
|
105
|
-
return [text, res, req];
|
|
106
|
-
});
|
|
107
|
-
}
|
|
108
|
-
async fetchJson(route, opts = {}) {
|
|
109
|
-
return this.fetchText(route, opts).then(([txt, res, req]) => [JSON.parse(txt), res, req]);
|
|
110
|
-
}
|
|
111
|
-
}
|
package/dist/File.d.ts
DELETED
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
import * as fs from 'node:fs';
|
|
2
|
-
import { Readable } from 'node:stream';
|
|
3
|
-
/**
|
|
4
|
-
* WARNING: API will change!
|
|
5
|
-
*/
|
|
6
|
-
export declare class File {
|
|
7
|
-
path: string;
|
|
8
|
-
constructor(filepath: string);
|
|
9
|
-
get exists(): boolean;
|
|
10
|
-
delete(): void;
|
|
11
|
-
read(): string | undefined;
|
|
12
|
-
/**
|
|
13
|
-
* @returns lines as strings, removes trailing '\n'
|
|
14
|
-
*/
|
|
15
|
-
lines(): string[];
|
|
16
|
-
get readStream(): fs.ReadStream | Readable;
|
|
17
|
-
get writeStream(): fs.WriteStream;
|
|
18
|
-
write(contents: string | ReadableStream): void | Promise<void>;
|
|
19
|
-
/**
|
|
20
|
-
* creates file if it doesn't exist, appends string or array of strings as new lines.
|
|
21
|
-
* File always ends with '\n', so contents don't need to be read before appending
|
|
22
|
-
*/
|
|
23
|
-
append(lines: string | string[]): void;
|
|
24
|
-
static get FileType(): typeof FileType;
|
|
25
|
-
json<T>(contents?: T): FileTypeJson<T>;
|
|
26
|
-
static get json(): typeof FileTypeJson;
|
|
27
|
-
ndjson<T extends object>(lines?: T | T[]): FileTypeNdjson<T>;
|
|
28
|
-
static get ndjson(): typeof FileTypeNdjson;
|
|
29
|
-
csv<T extends object>(rows?: T[], keys?: (keyof T)[]): Promise<FileTypeCsv<T>>;
|
|
30
|
-
static get csv(): typeof FileTypeCsv;
|
|
31
|
-
}
|
|
32
|
-
/**
|
|
33
|
-
* A generic file adaptor, extended by specific file type implementations
|
|
34
|
-
*/
|
|
35
|
-
export declare class FileType {
|
|
36
|
-
file: File;
|
|
37
|
-
constructor(filepath: string, contents?: string);
|
|
38
|
-
get exists(): boolean;
|
|
39
|
-
get path(): string;
|
|
40
|
-
delete(): void;
|
|
41
|
-
}
|
|
42
|
-
/**
|
|
43
|
-
* A .json file that maintains data type when reading/writing.
|
|
44
|
-
* This is unsafe! Type is not checked at runtime, avoid using on files manipulated outside of your application.
|
|
45
|
-
*/
|
|
46
|
-
export declare class FileTypeJson<T> extends FileType {
|
|
47
|
-
constructor(filepath: string, contents?: T);
|
|
48
|
-
read(): T | undefined;
|
|
49
|
-
write(contents: T): void;
|
|
50
|
-
}
|
|
51
|
-
/**
|
|
52
|
-
* New-line delimited json file (.ndjson)
|
|
53
|
-
* @see https://jsonltools.com/ndjson-format-specification
|
|
54
|
-
*/
|
|
55
|
-
export declare class FileTypeNdjson<T extends object> extends FileType {
|
|
56
|
-
constructor(filepath: string, lines?: T | T[]);
|
|
57
|
-
append(lines: T | T[]): void;
|
|
58
|
-
lines(): T[];
|
|
59
|
-
}
|
|
60
|
-
type Key<T extends object> = keyof T;
|
|
61
|
-
/**
|
|
62
|
-
* Comma separated values (.csv).
|
|
63
|
-
* Input rows as objects, keys are used as column headers
|
|
64
|
-
*/
|
|
65
|
-
export declare class FileTypeCsv<Row extends object> extends FileType {
|
|
66
|
-
#private;
|
|
67
|
-
constructor(filepath: string);
|
|
68
|
-
write(rows: Row[], keys?: Key<Row>[]): Promise<void>;
|
|
69
|
-
read(): Promise<Row[]>;
|
|
70
|
-
}
|
|
71
|
-
export {};
|