@brianbuie/node-kit 0.5.2 → 0.7.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 +535 -66
- package/dist/Cache.d.ts +12 -16
- package/dist/Cache.js +11 -5
- package/dist/Dir.d.ts +3 -3
- package/dist/Dir.js +3 -3
- package/dist/Fetcher.d.ts +6 -6
- package/dist/Fetcher.js +6 -6
- package/dist/File.d.ts +11 -11
- package/dist/File.js +12 -12
- package/dist/{_index.d.ts → index.d.ts} +1 -1
- package/dist/{_index.js → index.js} +1 -1
- package/package.json +6 -4
- package/src/Cache.ts +11 -5
- package/src/Dir.test.ts +4 -4
- package/src/Dir.ts +3 -4
- package/src/Fetcher.ts +6 -6
- package/src/File.test.ts +3 -3
- package/src/File.ts +12 -12
- package/src/{_index.ts → index.ts} +1 -1
package/README.md
CHANGED
|
@@ -4,110 +4,579 @@
|
|
|
4
4
|
|
|
5
5
|
Basic tools for quick node.js projects
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
# Installing
|
|
8
8
|
|
|
9
9
|
```
|
|
10
10
|
npm add @brianbuie/node-kit
|
|
11
11
|
```
|
|
12
12
|
|
|
13
13
|
```js
|
|
14
|
-
import {
|
|
14
|
+
import { Fetcher, Log } from '@brianbuie/node-kit';
|
|
15
15
|
```
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
# API
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
<!--#region ts2md-api-merged-here-->
|
|
20
|
+
|
|
21
|
+
Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types), [Variables](#variables)
|
|
22
|
+
|
|
23
|
+
# Classes
|
|
24
|
+
|
|
25
|
+
| |
|
|
26
|
+
| --- |
|
|
27
|
+
| [Cache](#class-cache) |
|
|
28
|
+
| [Dir](#class-dir) |
|
|
29
|
+
| [Fetcher](#class-fetcher) |
|
|
30
|
+
| [File](#class-file) |
|
|
31
|
+
| [FileType](#class-filetype) |
|
|
32
|
+
| [FileTypeCsv](#class-filetypecsv) |
|
|
33
|
+
| [FileTypeJson](#class-filetypejson) |
|
|
34
|
+
| [FileTypeNdjson](#class-filetypendjson) |
|
|
35
|
+
| [Jwt](#class-jwt) |
|
|
36
|
+
| [Log](#class-log) |
|
|
37
|
+
| [TempDir](#class-tempdir) |
|
|
38
|
+
| [TypeWriter](#class-typewriter) |
|
|
39
|
+
|
|
40
|
+
Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types), [Variables](#variables)
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## Class: Cache
|
|
45
|
+
|
|
46
|
+
Save results of a function in a temporary file.
|
|
20
47
|
|
|
21
48
|
```ts
|
|
22
|
-
|
|
49
|
+
export class Cache<T> {
|
|
50
|
+
file;
|
|
51
|
+
ttl;
|
|
52
|
+
getValue;
|
|
53
|
+
constructor(key: string, ttl: number, getValue: () => T | Promise<T>)
|
|
54
|
+
async read()
|
|
55
|
+
async write()
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types), [Variables](#variables)
|
|
23
60
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
61
|
+
---
|
|
62
|
+
## Class: Dir
|
|
63
|
+
|
|
64
|
+
Reference to a specific directory with helpful methods for resolving filepaths,
|
|
65
|
+
sanitizing filenames, and saving files.
|
|
66
|
+
|
|
67
|
+
```ts
|
|
68
|
+
export class Dir {
|
|
69
|
+
path;
|
|
70
|
+
constructor(_path: string)
|
|
71
|
+
create()
|
|
72
|
+
dir(subPath: string)
|
|
73
|
+
sanitize(name: string)
|
|
74
|
+
filepath(base: string)
|
|
75
|
+
file(base: string)
|
|
76
|
+
}
|
|
77
|
+
```
|
|
31
78
|
|
|
32
|
-
|
|
33
|
-
// returns [Response, Request]
|
|
34
|
-
const [res] = await api.fetch('/route');
|
|
79
|
+
<details>
|
|
35
80
|
|
|
36
|
-
|
|
37
|
-
// returns [string, Response, Request]
|
|
38
|
-
const [text] = await api.fetchText('/other-route');
|
|
81
|
+
<summary>Class Dir Details</summary>
|
|
39
82
|
|
|
40
|
-
|
|
41
|
-
// returns [Thing, Response, Request]
|
|
42
|
-
const [data] = await api.fetchJson<Thing>('/thing', { query: { page: 1 } });
|
|
83
|
+
### Constructor
|
|
43
84
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
const [result] = await api.fetchJson<Thing>('/thing', { data: { example: 1 } });
|
|
85
|
+
```ts
|
|
86
|
+
constructor(_path: string)
|
|
47
87
|
```
|
|
48
88
|
|
|
49
|
-
|
|
89
|
+
Argument Details
|
|
50
90
|
|
|
51
|
-
|
|
91
|
+
+ **path**
|
|
92
|
+
+ can be relative to workspace or absolute
|
|
52
93
|
|
|
53
|
-
|
|
54
|
-
import { Jwt, Fetcher } from '@brianbuie/node-kit';
|
|
94
|
+
### Method dir
|
|
55
95
|
|
|
56
|
-
|
|
57
|
-
payload: {
|
|
58
|
-
example: 'value',
|
|
59
|
-
},
|
|
60
|
-
options: {
|
|
61
|
-
algorithm: 'HS256',
|
|
62
|
-
},
|
|
63
|
-
seconds: 60,
|
|
64
|
-
key: process.env.JWT_KEY,
|
|
65
|
-
});
|
|
96
|
+
Create a new Dir inside the current Dir
|
|
66
97
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
headers: {
|
|
70
|
-
Authorization: `Bearer ${apiJwt.token}`,
|
|
71
|
-
},
|
|
72
|
-
});
|
|
98
|
+
```ts
|
|
99
|
+
dir(subPath: string)
|
|
73
100
|
```
|
|
74
101
|
|
|
75
|
-
|
|
102
|
+
Argument Details
|
|
76
103
|
|
|
77
|
-
|
|
104
|
+
+ **subPath**
|
|
105
|
+
+ to create in current Dir
|
|
78
106
|
|
|
79
|
-
|
|
107
|
+
Example
|
|
80
108
|
|
|
81
|
-
```
|
|
82
|
-
|
|
109
|
+
```ts
|
|
110
|
+
const folder = new Dir('example');
|
|
111
|
+
// folder.path = './example'
|
|
112
|
+
const child = folder.subDir('path/to/dir');
|
|
113
|
+
// child.path = './example/path/to/dir'
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### Method filepath
|
|
117
|
+
|
|
118
|
+
```ts
|
|
119
|
+
filepath(base: string)
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
Argument Details
|
|
83
123
|
|
|
84
|
-
|
|
124
|
+
+ **base**
|
|
125
|
+
+ The file name with extension
|
|
85
126
|
|
|
86
|
-
|
|
87
|
-
Log.debug('message', Response);
|
|
127
|
+
Example
|
|
88
128
|
|
|
89
|
-
|
|
90
|
-
|
|
129
|
+
```ts
|
|
130
|
+
const folder = new Dir('example');
|
|
131
|
+
const filepath = folder.resolve('file.json');
|
|
132
|
+
// 'example/file.json'
|
|
91
133
|
```
|
|
92
134
|
|
|
93
|
-
|
|
135
|
+
</details>
|
|
94
136
|
|
|
95
|
-
|
|
137
|
+
Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types), [Variables](#variables)
|
|
96
138
|
|
|
97
|
-
|
|
98
|
-
|
|
139
|
+
---
|
|
140
|
+
## Class: Fetcher
|
|
141
|
+
|
|
142
|
+
Fetcher provides a quick way to set up a basic API connection
|
|
143
|
+
with options applied to every request.
|
|
144
|
+
Includes basic methods for requesting and parsing responses
|
|
145
|
+
|
|
146
|
+
```ts
|
|
147
|
+
export class Fetcher {
|
|
148
|
+
defaultOptions;
|
|
149
|
+
constructor(opts: FetchOptions = {})
|
|
150
|
+
buildUrl(route: Route, opts: FetchOptions = {}): [
|
|
151
|
+
URL,
|
|
152
|
+
string
|
|
153
|
+
]
|
|
154
|
+
buildHeaders(route: Route, opts: FetchOptions = {})
|
|
155
|
+
buildRequest(route: Route, opts: FetchOptions = {}): [
|
|
156
|
+
Request,
|
|
157
|
+
FetchOptions,
|
|
158
|
+
string
|
|
159
|
+
]
|
|
160
|
+
async fetch(route: Route, opts: FetchOptions = {}): Promise<[
|
|
161
|
+
Response,
|
|
162
|
+
Request
|
|
163
|
+
]>
|
|
164
|
+
async fetchText(route: Route, opts: FetchOptions = {}): Promise<[
|
|
165
|
+
string,
|
|
166
|
+
Response,
|
|
167
|
+
Request
|
|
168
|
+
]>
|
|
169
|
+
async fetchJson<T>(route: Route, opts: FetchOptions = {}): Promise<[
|
|
170
|
+
T,
|
|
171
|
+
Response,
|
|
172
|
+
Request
|
|
173
|
+
]>
|
|
174
|
+
}
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
See also: [FetchOptions](#type-fetchoptions), [Route](#type-route)
|
|
178
|
+
|
|
179
|
+
<details>
|
|
180
|
+
|
|
181
|
+
<summary>Class Fetcher Details</summary>
|
|
182
|
+
|
|
183
|
+
### Method buildHeaders
|
|
184
|
+
|
|
185
|
+
Merges options to get headers. Useful when extending the Fetcher class to add custom auth.
|
|
186
|
+
|
|
187
|
+
```ts
|
|
188
|
+
buildHeaders(route: Route, opts: FetchOptions = {})
|
|
189
|
+
```
|
|
190
|
+
See also: [FetchOptions](#type-fetchoptions), [Route](#type-route)
|
|
191
|
+
|
|
192
|
+
### Method buildRequest
|
|
193
|
+
|
|
194
|
+
Builds request, merging defaultOptions and provided options.
|
|
195
|
+
Includes Abort signal for timeout
|
|
196
|
+
|
|
197
|
+
```ts
|
|
198
|
+
buildRequest(route: Route, opts: FetchOptions = {}): [
|
|
199
|
+
Request,
|
|
200
|
+
FetchOptions,
|
|
201
|
+
string
|
|
202
|
+
]
|
|
99
203
|
```
|
|
204
|
+
See also: [FetchOptions](#type-fetchoptions), [Route](#type-route)
|
|
100
205
|
|
|
101
|
-
|
|
206
|
+
### Method buildUrl
|
|
102
207
|
|
|
103
|
-
|
|
208
|
+
Build URL with URLSearchParams if query is provided.
|
|
209
|
+
Also returns domain, to help with cookies
|
|
104
210
|
|
|
211
|
+
```ts
|
|
212
|
+
buildUrl(route: Route, opts: FetchOptions = {}): [
|
|
213
|
+
URL,
|
|
214
|
+
string
|
|
215
|
+
]
|
|
105
216
|
```
|
|
106
|
-
|
|
217
|
+
See also: [FetchOptions](#type-fetchoptions), [Route](#type-route)
|
|
218
|
+
|
|
219
|
+
### Method fetch
|
|
220
|
+
|
|
221
|
+
Builds and performs the request, merging provided options with defaultOptions.
|
|
222
|
+
If `opts.data` is provided, method is updated to POST, content-type json, data is stringified in the body.
|
|
223
|
+
Retries on local or network error, with increasing backoff.
|
|
224
|
+
|
|
225
|
+
```ts
|
|
226
|
+
async fetch(route: Route, opts: FetchOptions = {}): Promise<[
|
|
227
|
+
Response,
|
|
228
|
+
Request
|
|
229
|
+
]>
|
|
107
230
|
```
|
|
231
|
+
See also: [FetchOptions](#type-fetchoptions), [Route](#type-route)
|
|
232
|
+
|
|
233
|
+
</details>
|
|
234
|
+
|
|
235
|
+
Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types), [Variables](#variables)
|
|
236
|
+
|
|
237
|
+
---
|
|
238
|
+
## Class: File
|
|
239
|
+
|
|
240
|
+
WARNING: API will change!
|
|
241
|
+
|
|
242
|
+
```ts
|
|
243
|
+
export class File {
|
|
244
|
+
path;
|
|
245
|
+
constructor(filepath: string)
|
|
246
|
+
get exists()
|
|
247
|
+
createWriteStream(options: Parameters<typeof fs.createWriteStream>[1] = {})
|
|
248
|
+
delete()
|
|
249
|
+
read()
|
|
250
|
+
write(contents: string)
|
|
251
|
+
append(lines: string | string[])
|
|
252
|
+
lines()
|
|
253
|
+
static get FileType()
|
|
254
|
+
json<T>(contents?: T)
|
|
255
|
+
static get json()
|
|
256
|
+
ndjson<T extends object>(lines?: T | T[])
|
|
257
|
+
static get ndjson()
|
|
258
|
+
async csv<T extends object>(rows?: T[], keys?: (keyof T)[])
|
|
259
|
+
static get csv()
|
|
260
|
+
}
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
See also: [FileType](#class-filetype)
|
|
264
|
+
|
|
265
|
+
<details>
|
|
266
|
+
|
|
267
|
+
<summary>Class File Details</summary>
|
|
268
|
+
|
|
269
|
+
### Method append
|
|
270
|
+
|
|
271
|
+
creates file if it doesn't exist, appends string or array of strings as new lines.
|
|
272
|
+
File always ends with '\n', so contents don't need to be read before appending
|
|
273
|
+
|
|
274
|
+
```ts
|
|
275
|
+
append(lines: string | string[])
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
### Method lines
|
|
279
|
+
|
|
280
|
+
```ts
|
|
281
|
+
lines()
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
Returns
|
|
285
|
+
|
|
286
|
+
lines as strings, removes trailing '\n'
|
|
287
|
+
|
|
288
|
+
</details>
|
|
289
|
+
|
|
290
|
+
Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types), [Variables](#variables)
|
|
291
|
+
|
|
292
|
+
---
|
|
293
|
+
## Class: FileType
|
|
294
|
+
|
|
295
|
+
```ts
|
|
296
|
+
export class FileType<T = string> {
|
|
297
|
+
file;
|
|
298
|
+
constructor(filepath: string, contents?: T)
|
|
299
|
+
get exists()
|
|
300
|
+
delete()
|
|
301
|
+
get path()
|
|
302
|
+
}
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types), [Variables](#variables)
|
|
306
|
+
|
|
307
|
+
---
|
|
308
|
+
## Class: FileTypeCsv
|
|
309
|
+
|
|
310
|
+
```ts
|
|
311
|
+
export class FileTypeCsv<Row extends object> extends FileType {
|
|
312
|
+
constructor(filepath: string)
|
|
313
|
+
async write(rows: Row[], keys?: Key<Row>[])
|
|
314
|
+
async read()
|
|
315
|
+
}
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
See also: [FileType](#class-filetype)
|
|
319
|
+
|
|
320
|
+
Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types), [Variables](#variables)
|
|
321
|
+
|
|
322
|
+
---
|
|
323
|
+
## Class: FileTypeJson
|
|
324
|
+
|
|
325
|
+
```ts
|
|
326
|
+
export class FileTypeJson<T> extends FileType {
|
|
327
|
+
constructor(filepath: string, contents?: T)
|
|
328
|
+
read()
|
|
329
|
+
write(contents: T)
|
|
330
|
+
}
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
See also: [FileType](#class-filetype)
|
|
334
|
+
|
|
335
|
+
Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types), [Variables](#variables)
|
|
336
|
+
|
|
337
|
+
---
|
|
338
|
+
## Class: FileTypeNdjson
|
|
339
|
+
|
|
340
|
+
```ts
|
|
341
|
+
export class FileTypeNdjson<T extends object> extends FileType {
|
|
342
|
+
constructor(filepath: string, lines?: T | T[])
|
|
343
|
+
append(lines: T | T[])
|
|
344
|
+
lines()
|
|
345
|
+
}
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
See also: [FileType](#class-filetype)
|
|
349
|
+
|
|
350
|
+
Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types), [Variables](#variables)
|
|
351
|
+
|
|
352
|
+
---
|
|
353
|
+
## Class: Jwt
|
|
354
|
+
|
|
355
|
+
```ts
|
|
356
|
+
export class Jwt {
|
|
357
|
+
config;
|
|
358
|
+
#saved?: {
|
|
359
|
+
exp: number;
|
|
360
|
+
token: string;
|
|
361
|
+
};
|
|
362
|
+
constructor(config: JwtConfig)
|
|
363
|
+
get now()
|
|
364
|
+
#createToken()
|
|
365
|
+
get token()
|
|
366
|
+
}
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types), [Variables](#variables)
|
|
370
|
+
|
|
371
|
+
---
|
|
372
|
+
## Class: Log
|
|
373
|
+
|
|
374
|
+
```ts
|
|
375
|
+
export class Log {
|
|
376
|
+
static isTest = process.env.npm_package_name === "@brianbuie/node-kit" && process.env.npm_lifecycle_event === "test";
|
|
377
|
+
static #toGcloud(entry: Entry)
|
|
378
|
+
static #toConsole(entry: Entry, color: ChalkInstance)
|
|
379
|
+
static #log(options: Options, ...input: unknown[])
|
|
380
|
+
static prepare(...input: unknown[]): {
|
|
381
|
+
message?: string;
|
|
382
|
+
details: unknown[];
|
|
383
|
+
}
|
|
384
|
+
static error(...input: unknown[])
|
|
385
|
+
static warn(...input: unknown[])
|
|
386
|
+
static notice(...input: unknown[])
|
|
387
|
+
static info(...input: unknown[])
|
|
388
|
+
static debug(...input: unknown[])
|
|
389
|
+
}
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
<details>
|
|
393
|
+
|
|
394
|
+
<summary>Class Log Details</summary>
|
|
395
|
+
|
|
396
|
+
### Method
|
|
397
|
+
|
|
398
|
+
Gcloud parses JSON in stdout
|
|
399
|
+
|
|
400
|
+
```ts
|
|
401
|
+
static #toGcloud(entry: Entry)
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
### Method
|
|
405
|
+
|
|
406
|
+
Includes colors and better inspection for logging during dev
|
|
407
|
+
|
|
408
|
+
```ts
|
|
409
|
+
static #toConsole(entry: Entry, color: ChalkInstance)
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
### Method error
|
|
413
|
+
|
|
414
|
+
Logs error details before throwing
|
|
415
|
+
|
|
416
|
+
```ts
|
|
417
|
+
static error(...input: unknown[])
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
### Method prepare
|
|
421
|
+
|
|
422
|
+
Handle first argument being a string or an object with a 'message' prop
|
|
423
|
+
Also snapshots special objects (eg Error, Response) to keep props in later JSON.stringify output
|
|
424
|
+
|
|
425
|
+
```ts
|
|
426
|
+
static prepare(...input: unknown[]): {
|
|
427
|
+
message?: string;
|
|
428
|
+
details: unknown[];
|
|
429
|
+
}
|
|
430
|
+
```
|
|
431
|
+
|
|
432
|
+
</details>
|
|
433
|
+
|
|
434
|
+
Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types), [Variables](#variables)
|
|
435
|
+
|
|
436
|
+
---
|
|
437
|
+
## Class: TempDir
|
|
438
|
+
|
|
439
|
+
Extends Dir class with method to `clear()` contents
|
|
440
|
+
|
|
441
|
+
```ts
|
|
442
|
+
export class TempDir extends Dir {
|
|
443
|
+
dir(subPath: string)
|
|
444
|
+
clear()
|
|
445
|
+
}
|
|
446
|
+
```
|
|
447
|
+
|
|
448
|
+
See also: [Dir](#class-dir)
|
|
449
|
+
|
|
450
|
+
Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types), [Variables](#variables)
|
|
451
|
+
|
|
452
|
+
---
|
|
453
|
+
## Class: TypeWriter
|
|
454
|
+
|
|
455
|
+
```ts
|
|
456
|
+
export class TypeWriter {
|
|
457
|
+
moduleName;
|
|
458
|
+
input = qt.jsonInputForTargetLanguage("typescript");
|
|
459
|
+
outDir;
|
|
460
|
+
qtSettings;
|
|
461
|
+
constructor(moduleName: string, settings: {
|
|
462
|
+
outDir?: string;
|
|
463
|
+
} & Partial<qt.Options> = {})
|
|
464
|
+
async addMember(name: string, _samples: any[])
|
|
465
|
+
async toString()
|
|
466
|
+
async toFile()
|
|
467
|
+
}
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
<details>
|
|
471
|
+
|
|
472
|
+
<summary>Class TypeWriter Details</summary>
|
|
473
|
+
|
|
474
|
+
### Method toString
|
|
475
|
+
|
|
476
|
+
function toString() { [native code] }
|
|
477
|
+
|
|
478
|
+
```ts
|
|
479
|
+
async toString()
|
|
480
|
+
```
|
|
481
|
+
|
|
482
|
+
</details>
|
|
483
|
+
|
|
484
|
+
Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types), [Variables](#variables)
|
|
485
|
+
|
|
486
|
+
---
|
|
487
|
+
# Functions
|
|
488
|
+
|
|
489
|
+
| |
|
|
490
|
+
| --- |
|
|
491
|
+
| [snapshot](#function-snapshot) |
|
|
492
|
+
| [timeout](#function-timeout) |
|
|
493
|
+
|
|
494
|
+
Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types), [Variables](#variables)
|
|
495
|
+
|
|
496
|
+
---
|
|
497
|
+
|
|
498
|
+
## Function: snapshot
|
|
499
|
+
|
|
500
|
+
Allows special objects (Error, Headers, Set) to be included in JSON.stringify output
|
|
501
|
+
functions are removed
|
|
502
|
+
|
|
503
|
+
```ts
|
|
504
|
+
export function snapshot(i: unknown, max = 50, depth = 0): any
|
|
505
|
+
```
|
|
506
|
+
|
|
507
|
+
Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types), [Variables](#variables)
|
|
508
|
+
|
|
509
|
+
---
|
|
510
|
+
## Function: timeout
|
|
511
|
+
|
|
512
|
+
```ts
|
|
513
|
+
export async function timeout(ms: number)
|
|
514
|
+
```
|
|
515
|
+
|
|
516
|
+
Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types), [Variables](#variables)
|
|
517
|
+
|
|
518
|
+
---
|
|
519
|
+
# Types
|
|
520
|
+
|
|
521
|
+
| |
|
|
522
|
+
| --- |
|
|
523
|
+
| [FetchOptions](#type-fetchoptions) |
|
|
524
|
+
| [Query](#type-query) |
|
|
525
|
+
| [Route](#type-route) |
|
|
526
|
+
|
|
527
|
+
Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types), [Variables](#variables)
|
|
528
|
+
|
|
529
|
+
---
|
|
530
|
+
|
|
531
|
+
## Type: FetchOptions
|
|
532
|
+
|
|
533
|
+
```ts
|
|
534
|
+
export type FetchOptions = RequestInit & {
|
|
535
|
+
base?: string;
|
|
536
|
+
query?: Query;
|
|
537
|
+
headers?: Record<string, string>;
|
|
538
|
+
data?: any;
|
|
539
|
+
timeout?: number;
|
|
540
|
+
retries?: number;
|
|
541
|
+
retryDelay?: number;
|
|
542
|
+
}
|
|
543
|
+
```
|
|
544
|
+
|
|
545
|
+
See also: [Query](#type-query), [timeout](#function-timeout)
|
|
546
|
+
|
|
547
|
+
Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types), [Variables](#variables)
|
|
548
|
+
|
|
549
|
+
---
|
|
550
|
+
## Type: Query
|
|
551
|
+
|
|
552
|
+
```ts
|
|
553
|
+
export type Query = Record<string, QueryVal | QueryVal[]>
|
|
554
|
+
```
|
|
555
|
+
|
|
556
|
+
Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types), [Variables](#variables)
|
|
557
|
+
|
|
558
|
+
---
|
|
559
|
+
## Type: Route
|
|
560
|
+
|
|
561
|
+
```ts
|
|
562
|
+
export type Route = string | URL
|
|
563
|
+
```
|
|
564
|
+
|
|
565
|
+
Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types), [Variables](#variables)
|
|
566
|
+
|
|
567
|
+
---
|
|
568
|
+
# Variables
|
|
569
|
+
|
|
570
|
+
## Variable: temp
|
|
571
|
+
|
|
572
|
+
```ts
|
|
573
|
+
temp = new TempDir(".temp")
|
|
574
|
+
```
|
|
575
|
+
|
|
576
|
+
See also: [TempDir](#class-tempdir)
|
|
577
|
+
|
|
578
|
+
Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types), [Variables](#variables)
|
|
579
|
+
|
|
580
|
+
---
|
|
108
581
|
|
|
109
|
-
-
|
|
110
|
-
- Runs tests (`"preversion"` script in `package.json`)
|
|
111
|
-
- Creates new commit, tagged with version
|
|
112
|
-
- Pushes commit and tags to github (`"postversion"` script in `package.json`)
|
|
113
|
-
- The new tag will trigger github action to publish to npm (`.github/actions/publish.yml`)
|
|
582
|
+
<!--#endregion ts2md-api-merged-here-->
|
package/dist/Cache.d.ts
CHANGED
|
@@ -1,21 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Save results of a function in a temporary file.
|
|
3
|
+
* @param key A unique name for the file
|
|
4
|
+
* @param ttl cache duration in ms
|
|
5
|
+
* @param getValue the function to populate the cache (eg. fetch results, generate key, etc)
|
|
6
|
+
*/
|
|
1
7
|
export declare class Cache<T> {
|
|
2
|
-
file: {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
} | undefined;
|
|
7
|
-
write(contents: {
|
|
8
|
-
createdAt: number;
|
|
9
|
-
value: T;
|
|
10
|
-
}): void;
|
|
11
|
-
file: import("./File.js").File;
|
|
12
|
-
get exists(): boolean;
|
|
13
|
-
delete(): void;
|
|
14
|
-
get path(): string;
|
|
15
|
-
};
|
|
8
|
+
file: import("./File.js").FileTypeJson<{
|
|
9
|
+
createdAt: number;
|
|
10
|
+
value: T;
|
|
11
|
+
}>;
|
|
16
12
|
ttl: number;
|
|
17
|
-
|
|
18
|
-
constructor(key: string, ttl: number,
|
|
13
|
+
getValue: () => T | Promise<T>;
|
|
14
|
+
constructor(key: string, ttl: number, getValue: () => T | Promise<T>);
|
|
19
15
|
read(): Promise<T>;
|
|
20
16
|
write(): Promise<T>;
|
|
21
17
|
}
|
package/dist/Cache.js
CHANGED
|
@@ -1,13 +1,19 @@
|
|
|
1
1
|
import { temp } from './Dir.js';
|
|
2
|
-
const cacheDir = temp.
|
|
2
|
+
const cacheDir = temp.dir('cache');
|
|
3
|
+
/**
|
|
4
|
+
* Save results of a function in a temporary file.
|
|
5
|
+
* @param key A unique name for the file
|
|
6
|
+
* @param ttl cache duration in ms
|
|
7
|
+
* @param getValue the function to populate the cache (eg. fetch results, generate key, etc)
|
|
8
|
+
*/
|
|
3
9
|
export class Cache {
|
|
4
10
|
file;
|
|
5
11
|
ttl;
|
|
6
|
-
|
|
7
|
-
constructor(key, ttl,
|
|
12
|
+
getValue;
|
|
13
|
+
constructor(key, ttl, getValue) {
|
|
8
14
|
this.file = cacheDir.file(key).json();
|
|
9
15
|
this.ttl = ttl;
|
|
10
|
-
this.
|
|
16
|
+
this.getValue = getValue;
|
|
11
17
|
}
|
|
12
18
|
async read() {
|
|
13
19
|
const { createdAt, value } = this.file.read() || {};
|
|
@@ -16,7 +22,7 @@ export class Cache {
|
|
|
16
22
|
return this.write();
|
|
17
23
|
}
|
|
18
24
|
async write() {
|
|
19
|
-
const value = await this.
|
|
25
|
+
const value = await this.getValue();
|
|
20
26
|
this.file.write({ createdAt: Date.now(), value });
|
|
21
27
|
return value;
|
|
22
28
|
}
|
package/dist/Dir.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { File } from './File.js';
|
|
2
2
|
/**
|
|
3
3
|
* Reference to a specific directory with helpful methods for resolving filepaths,
|
|
4
|
-
* sanitizing filenames, and saving files
|
|
4
|
+
* sanitizing filenames, and saving files.
|
|
5
5
|
*/
|
|
6
6
|
export declare class Dir {
|
|
7
7
|
path: string;
|
|
@@ -19,7 +19,7 @@ export declare class Dir {
|
|
|
19
19
|
* const child = folder.subDir('path/to/dir');
|
|
20
20
|
* // child.path = './example/path/to/dir'
|
|
21
21
|
*/
|
|
22
|
-
|
|
22
|
+
dir(subPath: string): Dir;
|
|
23
23
|
sanitize(name: string): string;
|
|
24
24
|
/**
|
|
25
25
|
* @param base - The file name with extension
|
|
@@ -35,7 +35,7 @@ export declare class Dir {
|
|
|
35
35
|
* Extends Dir class with method to `clear()` contents
|
|
36
36
|
*/
|
|
37
37
|
export declare class TempDir extends Dir {
|
|
38
|
-
|
|
38
|
+
dir(subPath: string): TempDir;
|
|
39
39
|
clear(): void;
|
|
40
40
|
}
|
|
41
41
|
/**
|
package/dist/Dir.js
CHANGED
|
@@ -4,7 +4,7 @@ import sanitizeFilename from 'sanitize-filename';
|
|
|
4
4
|
import { File } from './File.js';
|
|
5
5
|
/**
|
|
6
6
|
* Reference to a specific directory with helpful methods for resolving filepaths,
|
|
7
|
-
* sanitizing filenames, and saving files
|
|
7
|
+
* sanitizing filenames, and saving files.
|
|
8
8
|
*/
|
|
9
9
|
export class Dir {
|
|
10
10
|
path;
|
|
@@ -26,7 +26,7 @@ export class Dir {
|
|
|
26
26
|
* const child = folder.subDir('path/to/dir');
|
|
27
27
|
* // child.path = './example/path/to/dir'
|
|
28
28
|
*/
|
|
29
|
-
|
|
29
|
+
dir(subPath) {
|
|
30
30
|
return new Dir(path.resolve(this.path, subPath));
|
|
31
31
|
}
|
|
32
32
|
sanitize(name) {
|
|
@@ -50,7 +50,7 @@ export class Dir {
|
|
|
50
50
|
* Extends Dir class with method to `clear()` contents
|
|
51
51
|
*/
|
|
52
52
|
export class TempDir extends Dir {
|
|
53
|
-
|
|
53
|
+
dir(subPath) {
|
|
54
54
|
return new TempDir(path.resolve(this.path, subPath));
|
|
55
55
|
}
|
|
56
56
|
clear() {
|
package/dist/Fetcher.d.ts
CHANGED
|
@@ -12,7 +12,7 @@ export type FetchOptions = RequestInit & {
|
|
|
12
12
|
};
|
|
13
13
|
/**
|
|
14
14
|
* Fetcher provides a quick way to set up a basic API connection
|
|
15
|
-
* with options applied to every request
|
|
15
|
+
* with options applied to every request.
|
|
16
16
|
* Includes basic methods for requesting and parsing responses
|
|
17
17
|
*/
|
|
18
18
|
export declare class Fetcher {
|
|
@@ -40,7 +40,7 @@ export declare class Fetcher {
|
|
|
40
40
|
};
|
|
41
41
|
constructor(opts?: FetchOptions);
|
|
42
42
|
/**
|
|
43
|
-
* Build URL with URLSearchParams if query is provided
|
|
43
|
+
* Build URL with URLSearchParams if query is provided.
|
|
44
44
|
* Also returns domain, to help with cookies
|
|
45
45
|
*/
|
|
46
46
|
buildUrl(route: Route, opts?: FetchOptions): [URL, string];
|
|
@@ -49,14 +49,14 @@ export declare class Fetcher {
|
|
|
49
49
|
*/
|
|
50
50
|
buildHeaders(route: Route, opts?: FetchOptions): HeadersInit & Record<string, string>;
|
|
51
51
|
/**
|
|
52
|
-
* Builds request, merging defaultOptions and provided options
|
|
52
|
+
* Builds request, merging defaultOptions and provided options.
|
|
53
53
|
* Includes Abort signal for timeout
|
|
54
54
|
*/
|
|
55
55
|
buildRequest(route: Route, opts?: FetchOptions): [Request, FetchOptions, string];
|
|
56
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
|
|
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
60
|
*/
|
|
61
61
|
fetch(route: Route, opts?: FetchOptions): Promise<[Response, Request]>;
|
|
62
62
|
fetchText(route: Route, opts?: FetchOptions): Promise<[string, Response, Request]>;
|
package/dist/Fetcher.js
CHANGED
|
@@ -2,7 +2,7 @@ import { merge } from 'lodash-es';
|
|
|
2
2
|
import extractDomain from 'extract-domain';
|
|
3
3
|
/**
|
|
4
4
|
* Fetcher provides a quick way to set up a basic API connection
|
|
5
|
-
* with options applied to every request
|
|
5
|
+
* with options applied to every request.
|
|
6
6
|
* Includes basic methods for requesting and parsing responses
|
|
7
7
|
*/
|
|
8
8
|
export class Fetcher {
|
|
@@ -16,7 +16,7 @@ export class Fetcher {
|
|
|
16
16
|
};
|
|
17
17
|
}
|
|
18
18
|
/**
|
|
19
|
-
* Build URL with URLSearchParams if query is provided
|
|
19
|
+
* Build URL with URLSearchParams if query is provided.
|
|
20
20
|
* Also returns domain, to help with cookies
|
|
21
21
|
*/
|
|
22
22
|
buildUrl(route, opts = {}) {
|
|
@@ -47,7 +47,7 @@ export class Fetcher {
|
|
|
47
47
|
return headers || {};
|
|
48
48
|
}
|
|
49
49
|
/**
|
|
50
|
-
* Builds request, merging defaultOptions and provided options
|
|
50
|
+
* Builds request, merging defaultOptions and provided options.
|
|
51
51
|
* Includes Abort signal for timeout
|
|
52
52
|
*/
|
|
53
53
|
buildRequest(route, opts = {}) {
|
|
@@ -67,9 +67,9 @@ export class Fetcher {
|
|
|
67
67
|
return [req, mergedOptions, domain];
|
|
68
68
|
}
|
|
69
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
|
|
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
73
|
*/
|
|
74
74
|
async fetch(route, opts = {}) {
|
|
75
75
|
const [_req, options] = this.buildRequest(route, opts);
|
package/dist/File.d.ts
CHANGED
|
@@ -19,33 +19,33 @@ export declare class File {
|
|
|
19
19
|
* @returns lines as strings, removes trailing '\n'
|
|
20
20
|
*/
|
|
21
21
|
lines(): string[];
|
|
22
|
-
static get
|
|
23
|
-
json<T>(contents?: T):
|
|
24
|
-
static get json(): typeof
|
|
25
|
-
ndjson<T extends object>(lines?: T | T[]):
|
|
26
|
-
static get ndjson(): typeof
|
|
27
|
-
csv<T extends object>(rows?: T[], keys?: (keyof T)[]): Promise<
|
|
28
|
-
static get csv(): typeof
|
|
22
|
+
static get FileType(): typeof FileType;
|
|
23
|
+
json<T>(contents?: T): FileTypeJson<T>;
|
|
24
|
+
static get json(): typeof FileTypeJson;
|
|
25
|
+
ndjson<T extends object>(lines?: T | T[]): FileTypeNdjson<T>;
|
|
26
|
+
static get ndjson(): typeof FileTypeNdjson;
|
|
27
|
+
csv<T extends object>(rows?: T[], keys?: (keyof T)[]): Promise<FileTypeCsv<T>>;
|
|
28
|
+
static get csv(): typeof FileTypeCsv;
|
|
29
29
|
}
|
|
30
|
-
declare class
|
|
30
|
+
export declare class FileType<T = string> {
|
|
31
31
|
file: File;
|
|
32
32
|
constructor(filepath: string, contents?: T);
|
|
33
33
|
get exists(): boolean;
|
|
34
34
|
delete(): void;
|
|
35
35
|
get path(): string;
|
|
36
36
|
}
|
|
37
|
-
declare class
|
|
37
|
+
export declare class FileTypeJson<T> extends FileType {
|
|
38
38
|
constructor(filepath: string, contents?: T);
|
|
39
39
|
read(): T | undefined;
|
|
40
40
|
write(contents: T): void;
|
|
41
41
|
}
|
|
42
|
-
declare class
|
|
42
|
+
export declare class FileTypeNdjson<T extends object> extends FileType {
|
|
43
43
|
constructor(filepath: string, lines?: T | T[]);
|
|
44
44
|
append(lines: T | T[]): void;
|
|
45
45
|
lines(): T[];
|
|
46
46
|
}
|
|
47
47
|
type Key<T extends object> = keyof T;
|
|
48
|
-
declare class
|
|
48
|
+
export declare class FileTypeCsv<Row extends object> extends FileType {
|
|
49
49
|
constructor(filepath: string);
|
|
50
50
|
write(rows: Row[], keys?: Key<Row>[]): Promise<void>;
|
|
51
51
|
read(): Promise<Row[]>;
|
package/dist/File.js
CHANGED
|
@@ -43,32 +43,32 @@ export class File {
|
|
|
43
43
|
const contents = (this.read() || '').split('\n');
|
|
44
44
|
return contents.slice(0, contents.length - 1);
|
|
45
45
|
}
|
|
46
|
-
static get
|
|
47
|
-
return
|
|
46
|
+
static get FileType() {
|
|
47
|
+
return FileType;
|
|
48
48
|
}
|
|
49
49
|
json(contents) {
|
|
50
|
-
return new
|
|
50
|
+
return new FileTypeJson(this.path, contents);
|
|
51
51
|
}
|
|
52
52
|
static get json() {
|
|
53
|
-
return
|
|
53
|
+
return FileTypeJson;
|
|
54
54
|
}
|
|
55
55
|
ndjson(lines) {
|
|
56
|
-
return new
|
|
56
|
+
return new FileTypeNdjson(this.path, lines);
|
|
57
57
|
}
|
|
58
58
|
static get ndjson() {
|
|
59
|
-
return
|
|
59
|
+
return FileTypeNdjson;
|
|
60
60
|
}
|
|
61
61
|
async csv(rows, keys) {
|
|
62
|
-
const csvFile = new
|
|
62
|
+
const csvFile = new FileTypeCsv(this.path);
|
|
63
63
|
if (rows)
|
|
64
64
|
await csvFile.write(rows, keys);
|
|
65
65
|
return csvFile;
|
|
66
66
|
}
|
|
67
67
|
static get csv() {
|
|
68
|
-
return
|
|
68
|
+
return FileTypeCsv;
|
|
69
69
|
}
|
|
70
70
|
}
|
|
71
|
-
class
|
|
71
|
+
export class FileType {
|
|
72
72
|
file;
|
|
73
73
|
constructor(filepath, contents) {
|
|
74
74
|
this.file = new File(filepath);
|
|
@@ -89,7 +89,7 @@ class Adaptor {
|
|
|
89
89
|
return this.file.path;
|
|
90
90
|
}
|
|
91
91
|
}
|
|
92
|
-
class
|
|
92
|
+
export class FileTypeJson extends FileType {
|
|
93
93
|
constructor(filepath, contents) {
|
|
94
94
|
super(filepath.endsWith('.json') ? filepath : filepath + '.json');
|
|
95
95
|
if (contents)
|
|
@@ -103,7 +103,7 @@ class JsonFile extends Adaptor {
|
|
|
103
103
|
this.file.write(JSON.stringify(snapshot(contents), null, 2));
|
|
104
104
|
}
|
|
105
105
|
}
|
|
106
|
-
class
|
|
106
|
+
export class FileTypeNdjson extends FileType {
|
|
107
107
|
constructor(filepath, lines) {
|
|
108
108
|
super(filepath.endsWith('.ndjson') ? filepath : filepath + '.ndjson');
|
|
109
109
|
if (lines)
|
|
@@ -116,7 +116,7 @@ class NdjsonFile extends Adaptor {
|
|
|
116
116
|
return this.file.lines().map((l) => JSON.parse(l));
|
|
117
117
|
}
|
|
118
118
|
}
|
|
119
|
-
class
|
|
119
|
+
export class FileTypeCsv extends FileType {
|
|
120
120
|
constructor(filepath) {
|
|
121
121
|
super(filepath.endsWith('.csv') ? filepath : filepath + '.csv');
|
|
122
122
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { Dir, TempDir, temp } from './Dir.js';
|
|
2
2
|
export { Cache } from './Cache.js';
|
|
3
3
|
export { Fetcher, type Route, type Query, type FetchOptions } from './Fetcher.js';
|
|
4
|
-
export { File } from './File.js';
|
|
4
|
+
export { File, FileType, FileTypeJson, FileTypeNdjson, FileTypeCsv } from './File.js';
|
|
5
5
|
export { Jwt } from './Jwt.js';
|
|
6
6
|
export { Log } from './Log.js';
|
|
7
7
|
export { snapshot } from './snapshot.js';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { Dir, TempDir, temp } from './Dir.js';
|
|
2
2
|
export { Cache } from './Cache.js';
|
|
3
3
|
export { Fetcher } from './Fetcher.js';
|
|
4
|
-
export { File } from './File.js';
|
|
4
|
+
export { File, FileType, FileTypeJson, FileTypeNdjson, FileTypeCsv } from './File.js';
|
|
5
5
|
export { Jwt } from './Jwt.js';
|
|
6
6
|
export { Log } from './Log.js';
|
|
7
7
|
export { snapshot } from './snapshot.js';
|
package/package.json
CHANGED
|
@@ -1,21 +1,22 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@brianbuie/node-kit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
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
|
+
"docs": "node ./node_modules/ts2md/out/src/ts2md.js --firstHeadingLevel=1",
|
|
10
11
|
"test": "tsc && node --test \"dist/**/*.test.js\" --quiet",
|
|
11
|
-
"preversion": "npm test",
|
|
12
|
+
"preversion": "npm test && npm run docs",
|
|
12
13
|
"postversion": "git push --follow-tags"
|
|
13
14
|
},
|
|
14
15
|
"type": "module",
|
|
15
16
|
"exports": {
|
|
16
17
|
".": {
|
|
17
|
-
"types": "./dist/
|
|
18
|
-
"default": "./dist/
|
|
18
|
+
"types": "./dist/index.d.ts",
|
|
19
|
+
"default": "./dist/index.js"
|
|
19
20
|
}
|
|
20
21
|
},
|
|
21
22
|
"files": [
|
|
@@ -40,6 +41,7 @@
|
|
|
40
41
|
"@types/jsonwebtoken": "^9.0.10",
|
|
41
42
|
"@types/lodash-es": "^4.17.12",
|
|
42
43
|
"@types/node": "^24.9.1",
|
|
44
|
+
"ts2md": "^0.2.8",
|
|
43
45
|
"typescript": "^5.9.3"
|
|
44
46
|
}
|
|
45
47
|
}
|
package/src/Cache.ts
CHANGED
|
@@ -1,16 +1,22 @@
|
|
|
1
1
|
import { temp } from './Dir.js';
|
|
2
2
|
|
|
3
|
-
const cacheDir = temp.
|
|
3
|
+
const cacheDir = temp.dir('cache');
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* Save results of a function in a temporary file.
|
|
7
|
+
* @param key A unique name for the file
|
|
8
|
+
* @param ttl cache duration in ms
|
|
9
|
+
* @param getValue the function to populate the cache (eg. fetch results, generate key, etc)
|
|
10
|
+
*/
|
|
5
11
|
export class Cache<T> {
|
|
6
12
|
file;
|
|
7
13
|
ttl;
|
|
8
|
-
|
|
14
|
+
getValue;
|
|
9
15
|
|
|
10
|
-
constructor(key: string, ttl: number,
|
|
16
|
+
constructor(key: string, ttl: number, getValue: () => T | Promise<T>) {
|
|
11
17
|
this.file = cacheDir.file(key).json<{ createdAt: number; value: T }>();
|
|
12
18
|
this.ttl = ttl;
|
|
13
|
-
this.
|
|
19
|
+
this.getValue = getValue;
|
|
14
20
|
}
|
|
15
21
|
|
|
16
22
|
async read() {
|
|
@@ -20,7 +26,7 @@ export class Cache<T> {
|
|
|
20
26
|
}
|
|
21
27
|
|
|
22
28
|
async write() {
|
|
23
|
-
const value = await this.
|
|
29
|
+
const value = await this.getValue();
|
|
24
30
|
this.file.write({ createdAt: Date.now(), value });
|
|
25
31
|
return value;
|
|
26
32
|
}
|
package/src/Dir.test.ts
CHANGED
|
@@ -3,7 +3,7 @@ import assert from 'node:assert';
|
|
|
3
3
|
import { Dir, TempDir, temp } from './Dir.js';
|
|
4
4
|
|
|
5
5
|
describe('Dir', () => {
|
|
6
|
-
const testDir = temp.
|
|
6
|
+
const testDir = temp.dir('dir-test');
|
|
7
7
|
|
|
8
8
|
it('Sanitizes filenames', () => {
|
|
9
9
|
const name = testDir.sanitize(':/something/else.json');
|
|
@@ -13,13 +13,13 @@ describe('Dir', () => {
|
|
|
13
13
|
|
|
14
14
|
it('Creates sub directories', () => {
|
|
15
15
|
const subPath = 'sub/dir';
|
|
16
|
-
const sub = testDir.
|
|
16
|
+
const sub = testDir.dir(subPath);
|
|
17
17
|
assert(sub.path.includes(testDir.path));
|
|
18
18
|
assert(sub.path.includes(subPath));
|
|
19
19
|
});
|
|
20
20
|
|
|
21
|
-
it('TempDir.
|
|
22
|
-
const sub = temp.
|
|
21
|
+
it('TempDir.dir returns instance of TempDir', () => {
|
|
22
|
+
const sub = temp.dir('example');
|
|
23
23
|
assert(sub instanceof TempDir);
|
|
24
24
|
});
|
|
25
25
|
|
package/src/Dir.ts
CHANGED
|
@@ -2,11 +2,10 @@ import * as fs from 'node:fs';
|
|
|
2
2
|
import * as path from 'node:path';
|
|
3
3
|
import sanitizeFilename from 'sanitize-filename';
|
|
4
4
|
import { File } from './File.js';
|
|
5
|
-
import { snapshot } from './snapshot.js';
|
|
6
5
|
|
|
7
6
|
/**
|
|
8
7
|
* Reference to a specific directory with helpful methods for resolving filepaths,
|
|
9
|
-
* sanitizing filenames, and saving files
|
|
8
|
+
* sanitizing filenames, and saving files.
|
|
10
9
|
*/
|
|
11
10
|
export class Dir {
|
|
12
11
|
path;
|
|
@@ -31,7 +30,7 @@ export class Dir {
|
|
|
31
30
|
* const child = folder.subDir('path/to/dir');
|
|
32
31
|
* // child.path = './example/path/to/dir'
|
|
33
32
|
*/
|
|
34
|
-
|
|
33
|
+
dir(subPath: string) {
|
|
35
34
|
return new Dir(path.resolve(this.path, subPath));
|
|
36
35
|
}
|
|
37
36
|
|
|
@@ -59,7 +58,7 @@ export class Dir {
|
|
|
59
58
|
* Extends Dir class with method to `clear()` contents
|
|
60
59
|
*/
|
|
61
60
|
export class TempDir extends Dir {
|
|
62
|
-
|
|
61
|
+
dir(subPath: string) {
|
|
63
62
|
return new TempDir(path.resolve(this.path, subPath));
|
|
64
63
|
}
|
|
65
64
|
|
package/src/Fetcher.ts
CHANGED
|
@@ -18,7 +18,7 @@ export type FetchOptions = RequestInit & {
|
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
20
|
* Fetcher provides a quick way to set up a basic API connection
|
|
21
|
-
* with options applied to every request
|
|
21
|
+
* with options applied to every request.
|
|
22
22
|
* Includes basic methods for requesting and parsing responses
|
|
23
23
|
*/
|
|
24
24
|
export class Fetcher {
|
|
@@ -34,7 +34,7 @@ export class Fetcher {
|
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
/**
|
|
37
|
-
* Build URL with URLSearchParams if query is provided
|
|
37
|
+
* Build URL with URLSearchParams if query is provided.
|
|
38
38
|
* Also returns domain, to help with cookies
|
|
39
39
|
*/
|
|
40
40
|
buildUrl(route: Route, opts: FetchOptions = {}): [URL, string] {
|
|
@@ -65,7 +65,7 @@ export class Fetcher {
|
|
|
65
65
|
}
|
|
66
66
|
|
|
67
67
|
/**
|
|
68
|
-
* Builds request, merging defaultOptions and provided options
|
|
68
|
+
* Builds request, merging defaultOptions and provided options.
|
|
69
69
|
* Includes Abort signal for timeout
|
|
70
70
|
*/
|
|
71
71
|
buildRequest(route: Route, opts: FetchOptions = {}): [Request, FetchOptions, string] {
|
|
@@ -86,9 +86,9 @@ export class Fetcher {
|
|
|
86
86
|
}
|
|
87
87
|
|
|
88
88
|
/**
|
|
89
|
-
* Builds and performs the request, merging provided options with defaultOptions
|
|
90
|
-
* If `opts.data` is provided, method is updated to POST, content-type json, data is stringified in the body
|
|
91
|
-
* Retries on local or network error, with increasing backoff
|
|
89
|
+
* Builds and performs the request, merging provided options with defaultOptions.
|
|
90
|
+
* If `opts.data` is provided, method is updated to POST, content-type json, data is stringified in the body.
|
|
91
|
+
* Retries on local or network error, with increasing backoff.
|
|
92
92
|
*/
|
|
93
93
|
async fetch(route: Route, opts: FetchOptions = {}): Promise<[Response, Request]> {
|
|
94
94
|
const [_req, options] = this.buildRequest(route, opts);
|
package/src/File.test.ts
CHANGED
|
@@ -3,7 +3,7 @@ import assert from 'node:assert';
|
|
|
3
3
|
import { temp } from './Dir.js';
|
|
4
4
|
import { File } from './File.js';
|
|
5
5
|
|
|
6
|
-
const testDir = temp.
|
|
6
|
+
const testDir = temp.dir('file-test');
|
|
7
7
|
testDir.clear();
|
|
8
8
|
|
|
9
9
|
const thing = {
|
|
@@ -14,9 +14,9 @@ const thing = {
|
|
|
14
14
|
e: null,
|
|
15
15
|
};
|
|
16
16
|
|
|
17
|
-
describe('
|
|
17
|
+
describe('FileType', () => {
|
|
18
18
|
it('Creates instances', () => {
|
|
19
|
-
const test1 = new File.
|
|
19
|
+
const test1 = new File.FileType(testDir.filepath('test1.txt'));
|
|
20
20
|
assert(test1.file.path.includes('test1.txt'));
|
|
21
21
|
const base = 'test2';
|
|
22
22
|
const eg1 = new File.json(testDir.filepath(base));
|
package/src/File.ts
CHANGED
|
@@ -52,38 +52,38 @@ export class File {
|
|
|
52
52
|
return contents.slice(0, contents.length - 1);
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
-
static get
|
|
56
|
-
return
|
|
55
|
+
static get FileType() {
|
|
56
|
+
return FileType;
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
json<T>(contents?: T) {
|
|
60
|
-
return new
|
|
60
|
+
return new FileTypeJson<T>(this.path, contents);
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
static get json() {
|
|
64
|
-
return
|
|
64
|
+
return FileTypeJson;
|
|
65
65
|
}
|
|
66
66
|
|
|
67
67
|
ndjson<T extends object>(lines?: T | T[]) {
|
|
68
|
-
return new
|
|
68
|
+
return new FileTypeNdjson<T>(this.path, lines);
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
static get ndjson() {
|
|
72
|
-
return
|
|
72
|
+
return FileTypeNdjson;
|
|
73
73
|
}
|
|
74
74
|
|
|
75
75
|
async csv<T extends object>(rows?: T[], keys?: (keyof T)[]) {
|
|
76
|
-
const csvFile = new
|
|
76
|
+
const csvFile = new FileTypeCsv<T>(this.path);
|
|
77
77
|
if (rows) await csvFile.write(rows, keys);
|
|
78
78
|
return csvFile;
|
|
79
79
|
}
|
|
80
80
|
|
|
81
81
|
static get csv() {
|
|
82
|
-
return
|
|
82
|
+
return FileTypeCsv;
|
|
83
83
|
}
|
|
84
84
|
}
|
|
85
85
|
|
|
86
|
-
class
|
|
86
|
+
export class FileType<T = string> {
|
|
87
87
|
file;
|
|
88
88
|
|
|
89
89
|
constructor(filepath: string, contents?: T) {
|
|
@@ -109,7 +109,7 @@ class Adaptor<T = string> {
|
|
|
109
109
|
}
|
|
110
110
|
}
|
|
111
111
|
|
|
112
|
-
class
|
|
112
|
+
export class FileTypeJson<T> extends FileType {
|
|
113
113
|
constructor(filepath: string, contents?: T) {
|
|
114
114
|
super(filepath.endsWith('.json') ? filepath : filepath + '.json');
|
|
115
115
|
if (contents) this.write(contents);
|
|
@@ -125,7 +125,7 @@ class JsonFile<T> extends Adaptor {
|
|
|
125
125
|
}
|
|
126
126
|
}
|
|
127
127
|
|
|
128
|
-
class
|
|
128
|
+
export class FileTypeNdjson<T extends object> extends FileType {
|
|
129
129
|
constructor(filepath: string, lines?: T | T[]) {
|
|
130
130
|
super(filepath.endsWith('.ndjson') ? filepath : filepath + '.ndjson');
|
|
131
131
|
if (lines) this.append(lines);
|
|
@@ -144,7 +144,7 @@ class NdjsonFile<T extends object> extends Adaptor {
|
|
|
144
144
|
|
|
145
145
|
type Key<T extends object> = keyof T;
|
|
146
146
|
|
|
147
|
-
class
|
|
147
|
+
export class FileTypeCsv<Row extends object> extends FileType {
|
|
148
148
|
constructor(filepath: string) {
|
|
149
149
|
super(filepath.endsWith('.csv') ? filepath : filepath + '.csv');
|
|
150
150
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { Dir, TempDir, temp } from './Dir.js';
|
|
2
2
|
export { Cache } from './Cache.js';
|
|
3
3
|
export { Fetcher, type Route, type Query, type FetchOptions } from './Fetcher.js';
|
|
4
|
-
export { File } from './File.js';
|
|
4
|
+
export { File, FileType, FileTypeJson, FileTypeNdjson, FileTypeCsv } from './File.js';
|
|
5
5
|
export { Jwt } from './Jwt.js';
|
|
6
6
|
export { Log } from './Log.js';
|
|
7
7
|
export { snapshot } from './snapshot.js';
|