@brianbuie/node-kit 0.8.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/README.md +18 -6
- 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 +34 -30
- package/src/File.ts +56 -41
- 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 -53
- package/dist/File.js +0 -170
- 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/README.md
CHANGED
|
@@ -249,10 +249,11 @@ export class File {
|
|
|
249
249
|
get exists()
|
|
250
250
|
delete()
|
|
251
251
|
read()
|
|
252
|
-
write(contents: string)
|
|
253
|
-
async streamFrom(...options: Parameters<(typeof Readable)["from"]>)
|
|
254
|
-
append(lines: string | string[])
|
|
255
252
|
lines()
|
|
253
|
+
get readStream()
|
|
254
|
+
get writeStream()
|
|
255
|
+
write(contents: string | ReadableStream)
|
|
256
|
+
append(lines: string | string[])
|
|
256
257
|
static get FileType()
|
|
257
258
|
json<T>(contents?: T)
|
|
258
259
|
static get json()
|
|
@@ -295,13 +296,15 @@ Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types
|
|
|
295
296
|
---
|
|
296
297
|
## Class: FileType
|
|
297
298
|
|
|
299
|
+
A generic file adaptor, extended by specific file type implementations
|
|
300
|
+
|
|
298
301
|
```ts
|
|
299
|
-
export class FileType
|
|
302
|
+
export class FileType {
|
|
300
303
|
file;
|
|
301
|
-
constructor(filepath: string, contents?:
|
|
304
|
+
constructor(filepath: string, contents?: string)
|
|
302
305
|
get exists()
|
|
303
|
-
delete()
|
|
304
306
|
get path()
|
|
307
|
+
delete()
|
|
305
308
|
}
|
|
306
309
|
```
|
|
307
310
|
|
|
@@ -310,10 +313,14 @@ Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types
|
|
|
310
313
|
---
|
|
311
314
|
## Class: FileTypeCsv
|
|
312
315
|
|
|
316
|
+
Comma separated values (.csv).
|
|
317
|
+
Input rows as objects, keys are used as column headers
|
|
318
|
+
|
|
313
319
|
```ts
|
|
314
320
|
export class FileTypeCsv<Row extends object> extends FileType {
|
|
315
321
|
constructor(filepath: string)
|
|
316
322
|
async write(rows: Row[], keys?: Key<Row>[])
|
|
323
|
+
#parseVal(val: string)
|
|
317
324
|
async read()
|
|
318
325
|
}
|
|
319
326
|
```
|
|
@@ -325,6 +332,9 @@ Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types
|
|
|
325
332
|
---
|
|
326
333
|
## Class: FileTypeJson
|
|
327
334
|
|
|
335
|
+
A .json file that maintains data type when reading/writing.
|
|
336
|
+
This is unsafe! Type is not checked at runtime, avoid using on files manipulated outside of your application.
|
|
337
|
+
|
|
328
338
|
```ts
|
|
329
339
|
export class FileTypeJson<T> extends FileType {
|
|
330
340
|
constructor(filepath: string, contents?: T)
|
|
@@ -340,6 +350,8 @@ Links: [API](#api), [Classes](#classes), [Functions](#functions), [Types](#types
|
|
|
340
350
|
---
|
|
341
351
|
## Class: FileTypeNdjson
|
|
342
352
|
|
|
353
|
+
New-line delimited json file (.ndjson)
|
|
354
|
+
|
|
343
355
|
```ts
|
|
344
356
|
export class FileTypeNdjson<T extends object> extends FileType {
|
|
345
357
|
constructor(filepath: string, lines?: T | T[])
|
package/package.json
CHANGED
|
@@ -1,28 +1,27 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@brianbuie/node-kit",
|
|
3
|
-
"version": "0.
|
|
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();
|
|
@@ -14,6 +14,17 @@ const thing = {
|
|
|
14
14
|
e: null,
|
|
15
15
|
};
|
|
16
16
|
|
|
17
|
+
describe('File', () => {
|
|
18
|
+
it('Handles request body as stream input', async () => {
|
|
19
|
+
const img = testDir.file('image.jpg');
|
|
20
|
+
await fetch('https://testingbot.com/free-online-tools/random-avatar/300').then((res) => {
|
|
21
|
+
if (!res.body) throw new Error('No response body');
|
|
22
|
+
return img.write(res.body);
|
|
23
|
+
});
|
|
24
|
+
assert(img.exists);
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
|
|
17
28
|
describe('FileType', () => {
|
|
18
29
|
it('Creates instances', () => {
|
|
19
30
|
const test1 = new File.FileType(testDir.filepath('test1.txt'));
|
|
@@ -35,20 +46,23 @@ describe('FileType', () => {
|
|
|
35
46
|
});
|
|
36
47
|
});
|
|
37
48
|
|
|
38
|
-
describe('
|
|
39
|
-
it('
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
49
|
+
describe('FileTypeJson', () => {
|
|
50
|
+
it('Saves data as json', () => {
|
|
51
|
+
const file = testDir.file('jsonfile-data').json(thing);
|
|
52
|
+
assert.deepStrictEqual(file.read(), thing);
|
|
53
|
+
file.write(thing);
|
|
54
|
+
assert.deepStrictEqual(file.read(), thing);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it('Does not create file when reading', () => {
|
|
58
|
+
const file = testDir.file('test123').json();
|
|
59
|
+
const contents = file.read();
|
|
60
|
+
assert(contents === undefined);
|
|
61
|
+
assert(!file.exists);
|
|
48
62
|
});
|
|
49
63
|
});
|
|
50
64
|
|
|
51
|
-
describe('
|
|
65
|
+
describe('FileTypeNdjson', () => {
|
|
52
66
|
it('Appends new lines correctly', () => {
|
|
53
67
|
const file = testDir.file('appends-lines').ndjson();
|
|
54
68
|
file.delete();
|
|
@@ -70,23 +84,7 @@ describe('File.ndjson', () => {
|
|
|
70
84
|
});
|
|
71
85
|
});
|
|
72
86
|
|
|
73
|
-
describe('
|
|
74
|
-
it('Saves data as json', () => {
|
|
75
|
-
const file = testDir.file('jsonfile-data').json(thing);
|
|
76
|
-
assert.deepStrictEqual(file.read(), thing);
|
|
77
|
-
file.write(thing);
|
|
78
|
-
assert.deepStrictEqual(file.read(), thing);
|
|
79
|
-
});
|
|
80
|
-
|
|
81
|
-
it('Does not create file when reading', () => {
|
|
82
|
-
const file = testDir.file('test123').json();
|
|
83
|
-
const contents = file.read();
|
|
84
|
-
assert(contents === undefined);
|
|
85
|
-
assert(!file.exists);
|
|
86
|
-
});
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
describe('File.csv', () => {
|
|
87
|
+
describe('FileTypeCsv', () => {
|
|
90
88
|
it('Saves data as csv', async () => {
|
|
91
89
|
const things = [thing, thing, thing];
|
|
92
90
|
const file = await testDir.file('csv-data').csv(things);
|
|
@@ -95,4 +93,10 @@ describe('File.csv', () => {
|
|
|
95
93
|
assert.deepEqual(row, thing);
|
|
96
94
|
});
|
|
97
95
|
});
|
|
96
|
+
it('Reads file that does not exist', async () => {
|
|
97
|
+
const file = await testDir.file('bogus').csv();
|
|
98
|
+
const contents = await file.read();
|
|
99
|
+
assert(Array.isArray(contents));
|
|
100
|
+
assert(contents.length === 0);
|
|
101
|
+
});
|
|
98
102
|
});
|
package/src/File.ts
CHANGED
|
@@ -2,8 +2,8 @@ import * as fs from 'node:fs';
|
|
|
2
2
|
import * as path from 'node:path';
|
|
3
3
|
import { Readable } from 'node:stream';
|
|
4
4
|
import { finished } from 'node:stream/promises';
|
|
5
|
-
import {
|
|
6
|
-
import { snapshot } from './snapshot.
|
|
5
|
+
import { writeToStream, parseStream } from 'fast-csv';
|
|
6
|
+
import { snapshot } from './snapshot.ts';
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* WARNING: API will change!
|
|
@@ -27,13 +27,28 @@ export class File {
|
|
|
27
27
|
return this.exists ? fs.readFileSync(this.path, 'utf8') : undefined;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
|
|
30
|
+
/**
|
|
31
|
+
* @returns lines as strings, removes trailing '\n'
|
|
32
|
+
*/
|
|
33
|
+
lines() {
|
|
34
|
+
const contents = (this.read() || '').split('\n');
|
|
35
|
+
return contents.slice(0, contents.length - 1);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
get readStream() {
|
|
39
|
+
return this.exists ? fs.createReadStream(this.path) : Readable.from([]);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
get writeStream() {
|
|
31
43
|
fs.mkdirSync(path.parse(this.path).dir, { recursive: true });
|
|
32
|
-
fs.
|
|
44
|
+
return fs.createWriteStream(this.path);
|
|
33
45
|
}
|
|
34
46
|
|
|
35
|
-
|
|
36
|
-
|
|
47
|
+
write(contents: string | ReadableStream) {
|
|
48
|
+
fs.mkdirSync(path.parse(this.path).dir, { recursive: true });
|
|
49
|
+
if (typeof contents === 'string') return fs.writeFileSync(this.path, contents);
|
|
50
|
+
if (contents instanceof ReadableStream) return finished(Readable.from(contents).pipe(this.writeStream));
|
|
51
|
+
throw new Error(`Invalid content type: ${typeof contents}`);
|
|
37
52
|
}
|
|
38
53
|
|
|
39
54
|
/**
|
|
@@ -46,14 +61,6 @@ export class File {
|
|
|
46
61
|
fs.appendFileSync(this.path, contents + '\n');
|
|
47
62
|
}
|
|
48
63
|
|
|
49
|
-
/**
|
|
50
|
-
* @returns lines as strings, removes trailing '\n'
|
|
51
|
-
*/
|
|
52
|
-
lines() {
|
|
53
|
-
const contents = (this.read() || '').split('\n');
|
|
54
|
-
return contents.slice(0, contents.length - 1);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
64
|
static get FileType() {
|
|
58
65
|
return FileType;
|
|
59
66
|
}
|
|
@@ -85,32 +92,34 @@ export class File {
|
|
|
85
92
|
}
|
|
86
93
|
}
|
|
87
94
|
|
|
88
|
-
|
|
95
|
+
/**
|
|
96
|
+
* A generic file adaptor, extended by specific file type implementations
|
|
97
|
+
*/
|
|
98
|
+
export class FileType {
|
|
89
99
|
file;
|
|
90
100
|
|
|
91
|
-
constructor(filepath: string, contents?:
|
|
101
|
+
constructor(filepath: string, contents?: string) {
|
|
92
102
|
this.file = new File(filepath);
|
|
93
|
-
if (contents)
|
|
94
|
-
if (typeof contents !== 'string') {
|
|
95
|
-
throw new Error('File contents must be a string');
|
|
96
|
-
}
|
|
97
|
-
this.file.write(contents);
|
|
98
|
-
}
|
|
103
|
+
if (contents) this.file.write(contents);
|
|
99
104
|
}
|
|
100
105
|
|
|
101
106
|
get exists() {
|
|
102
107
|
return this.file.exists;
|
|
103
108
|
}
|
|
104
109
|
|
|
105
|
-
delete() {
|
|
106
|
-
this.file.delete();
|
|
107
|
-
}
|
|
108
|
-
|
|
109
110
|
get path() {
|
|
110
111
|
return this.file.path;
|
|
111
112
|
}
|
|
113
|
+
|
|
114
|
+
delete() {
|
|
115
|
+
this.file.delete();
|
|
116
|
+
}
|
|
112
117
|
}
|
|
113
118
|
|
|
119
|
+
/**
|
|
120
|
+
* A .json file that maintains data type when reading/writing.
|
|
121
|
+
* This is unsafe! Type is not checked at runtime, avoid using on files manipulated outside of your application.
|
|
122
|
+
*/
|
|
114
123
|
export class FileTypeJson<T> extends FileType {
|
|
115
124
|
constructor(filepath: string, contents?: T) {
|
|
116
125
|
super(filepath.endsWith('.json') ? filepath : filepath + '.json');
|
|
@@ -127,6 +136,10 @@ export class FileTypeJson<T> extends FileType {
|
|
|
127
136
|
}
|
|
128
137
|
}
|
|
129
138
|
|
|
139
|
+
/**
|
|
140
|
+
* New-line delimited json file (.ndjson)
|
|
141
|
+
* @see https://jsonltools.com/ndjson-format-specification
|
|
142
|
+
*/
|
|
130
143
|
export class FileTypeNdjson<T extends object> extends FileType {
|
|
131
144
|
constructor(filepath: string, lines?: T | T[]) {
|
|
132
145
|
super(filepath.endsWith('.ndjson') ? filepath : filepath + '.ndjson');
|
|
@@ -146,6 +159,10 @@ export class FileTypeNdjson<T extends object> extends FileType {
|
|
|
146
159
|
|
|
147
160
|
type Key<T extends object> = keyof T;
|
|
148
161
|
|
|
162
|
+
/**
|
|
163
|
+
* Comma separated values (.csv).
|
|
164
|
+
* Input rows as objects, keys are used as column headers
|
|
165
|
+
*/
|
|
149
166
|
export class FileTypeCsv<Row extends object> extends FileType {
|
|
150
167
|
constructor(filepath: string) {
|
|
151
168
|
super(filepath.endsWith('.csv') ? filepath : filepath + '.csv');
|
|
@@ -162,36 +179,34 @@ export class FileTypeCsv<Row extends object> extends FileType {
|
|
|
162
179
|
}
|
|
163
180
|
const headers = Array.from(headerSet);
|
|
164
181
|
const outRows = rows.map((row) => headers.map((key) => row[key]));
|
|
165
|
-
|
|
166
|
-
|
|
182
|
+
return finished(writeToStream(this.file.writeStream, [headers, ...outRows]));
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
#parseVal(val: string) {
|
|
186
|
+
if (val.toLowerCase() === 'false') return false;
|
|
187
|
+
if (val.toLowerCase() === 'true') return true;
|
|
188
|
+
if (val.length === 0) return null;
|
|
189
|
+
if (/^[\.0-9]+$/.test(val)) return Number(val);
|
|
190
|
+
return val;
|
|
167
191
|
}
|
|
168
192
|
|
|
169
193
|
async read() {
|
|
170
194
|
return new Promise<Row[]>((resolve, reject) => {
|
|
171
195
|
const parsed: Row[] = [];
|
|
172
|
-
|
|
173
|
-
if (!content) return resolve(parsed);
|
|
174
|
-
function parseVal(val: string) {
|
|
175
|
-
if (val.toLowerCase() === 'false') return false;
|
|
176
|
-
if (val.toLowerCase() === 'true') return true;
|
|
177
|
-
if (val.length === 0) return null;
|
|
178
|
-
if (/^[\.0-9]+$/.test(val)) return Number(val);
|
|
179
|
-
return val;
|
|
180
|
-
}
|
|
181
|
-
parseString(content, { headers: true })
|
|
196
|
+
parseStream(this.file.readStream, { headers: true })
|
|
182
197
|
.on('error', (e) => reject(e))
|
|
183
|
-
.on('end', () => resolve(parsed))
|
|
184
198
|
.on('data', (raw: Record<Key<Row>, string>) => {
|
|
185
199
|
parsed.push(
|
|
186
200
|
Object.entries(raw).reduce(
|
|
187
201
|
(all, [key, val]) => ({
|
|
188
202
|
...all,
|
|
189
|
-
[key]: parseVal(val as string),
|
|
203
|
+
[key]: this.#parseVal(val as string),
|
|
190
204
|
}),
|
|
191
205
|
{} as Row,
|
|
192
206
|
),
|
|
193
207
|
);
|
|
194
|
-
})
|
|
208
|
+
})
|
|
209
|
+
.on('end', () => resolve(parsed));
|
|
195
210
|
});
|
|
196
211
|
}
|
|
197
212
|
}
|
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');
|