jg-fs 1.0.1 → 1.1.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/API.md +1716 -0
- package/CHANGELOG.md +20 -16
- package/README.md +6 -21
- package/dist/async/directories/directories.d.ts +14 -0
- package/dist/async/directories/directories.js +20 -2
- package/dist/async/directories/directories.js.map +1 -1
- package/dist/async/files/files.d.ts +46 -8
- package/dist/async/files/files.js +48 -10
- package/dist/async/files/files.js.map +1 -1
- package/dist/async/files/index.d.ts +1 -1
- package/dist/async/files/index.js +1 -1
- package/dist/async/files/index.js.map +1 -1
- package/dist/async/general/general.d.ts +4 -0
- package/dist/async/general/general.js +4 -0
- package/dist/async/general/general.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/shared/index.d.ts +2 -2
- package/dist/shared/index.js +1 -1
- package/dist/shared/index.js.map +1 -1
- package/dist/shared/paths.d.ts +2 -0
- package/dist/shared/paths.js +2 -0
- package/dist/shared/paths.js.map +1 -1
- package/dist/shared/types.d.ts +6 -0
- package/dist/shared/types.js.map +1 -1
- package/dist/shared/validations.d.ts +5 -3
- package/dist/shared/validations.js +30 -14
- package/dist/shared/validations.js.map +1 -1
- package/dist/sync/directories/directories.d.ts +14 -0
- package/dist/sync/directories/directories.js +20 -2
- package/dist/sync/directories/directories.js.map +1 -1
- package/dist/sync/files/files.d.ts +46 -8
- package/dist/sync/files/files.js +48 -10
- package/dist/sync/files/files.js.map +1 -1
- package/dist/sync/files/index.d.ts +1 -1
- package/dist/sync/files/index.js +1 -1
- package/dist/sync/files/index.js.map +1 -1
- package/dist/sync/general/general.d.ts +4 -0
- package/dist/sync/general/general.js +4 -0
- package/dist/sync/general/general.js.map +1 -1
- package/dist/sync/index.d.ts +2 -2
- package/dist/sync/index.js +1 -1
- package/dist/sync/index.js.map +1 -1
- package/package.json +10 -6
package/API.md
ADDED
|
@@ -0,0 +1,1716 @@
|
|
|
1
|
+
# <a id="api-reference"></a>jg-fs API reference
|
|
2
|
+
|
|
3
|
+
Every export of `jg-fs@1.1.0`, 62 in all, with its signature, its errors, and an example. It's generated from the package's TSDoc.
|
|
4
|
+
|
|
5
|
+
## <a id="api-entry-main"></a>`jg-fs`
|
|
6
|
+
|
|
7
|
+
- Functions: [`copyDirectory`](#api-copyDirectory), [`copyFile`](#api-copyFile), [`createDirectory`](#api-createDirectory), [`createDirectorySymLink`](#api-createDirectorySymLink), [`createFileSymLink`](#api-createFileSymLink), [`deleteDirectory`](#api-deleteDirectory), [`deleteFile`](#api-deleteFile), [`getDirectoryElements`](#api-getDirectoryElements), [`getPathElement`](#api-getPathElement), [`isDirectory`](#api-isDirectory), [`isFile`](#api-isFile), [`isPathWithin`](#api-isPathWithin), [`pathExists`](#api-pathExists), [`readBoundedFile`](#api-readBoundedFile), [`readBufferFile`](#api-readBufferFile), [`readDirectory`](#api-readDirectory), [`readFile`](#api-readFile), [`readJsonFile`](#api-readJsonFile), [`readTextFile`](#api-readTextFile), [`writeBufferFile`](#api-writeBufferFile), [`writeFile`](#api-writeFile), [`writeFileAtomic`](#api-writeFileAtomic), [`writeJsonFile`](#api-writeJsonFile), [`writeTextFile`](#api-writeTextFile)
|
|
8
|
+
- Constants: [`ERRORS`](#api-ERRORS)
|
|
9
|
+
- Types: [`IDirectoryElementsKeySort`](#api-IDirectoryElementsKeySort), [`IDirectoryElementsOptions`](#api-IDirectoryElementsOptions), [`IDirectoryPathElements`](#api-IDirectoryPathElements), [`IPathElement`](#api-IPathElement), [`IReadJsonFileOptions`](#api-IReadJsonFileOptions), [`ISchema`](#api-ISchema)
|
|
10
|
+
|
|
11
|
+
### <a id="api-functions"></a>Functions in `jg-fs`
|
|
12
|
+
|
|
13
|
+
#### <a id="api-copyDirectory"></a>`copyDirectory`
|
|
14
|
+
|
|
15
|
+
*Function*
|
|
16
|
+
|
|
17
|
+
Copies a directory and everything in it, replacing the destination completely.
|
|
18
|
+
|
|
19
|
+
```ts
|
|
20
|
+
copyDirectory(srcPath: string, destPath: string): Promise<void>
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
**Parameters**
|
|
24
|
+
|
|
25
|
+
- `srcPath` `string`: The directory to copy.
|
|
26
|
+
- `destPath` `string`: Where to copy it.
|
|
27
|
+
|
|
28
|
+
**Returns** `Promise<void>`: A promise that resolves once the copy is complete.
|
|
29
|
+
|
|
30
|
+
**Throws**
|
|
31
|
+
|
|
32
|
+
- `NOT_A_DIRECTORY`: if the srcPath is not a directory
|
|
33
|
+
|
|
34
|
+
**Example**
|
|
35
|
+
|
|
36
|
+
```ts
|
|
37
|
+
import { copyDirectory } from 'jg-fs';
|
|
38
|
+
|
|
39
|
+
await copyDirectory('templates', 'dist/templates');
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
#### <a id="api-copyFile"></a>`copyFile`
|
|
43
|
+
|
|
44
|
+
*Function*
|
|
45
|
+
|
|
46
|
+
Copies a file, replacing the destination when it exists.
|
|
47
|
+
|
|
48
|
+
```ts
|
|
49
|
+
copyFile(srcPath: string, destPath: string): Promise<void>
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
**Parameters**
|
|
53
|
+
|
|
54
|
+
- `srcPath` `string`: The file to copy.
|
|
55
|
+
- `destPath` `string`: Where to copy it.
|
|
56
|
+
|
|
57
|
+
**Returns** `Promise<void>`: A promise that resolves once the copy exists.
|
|
58
|
+
|
|
59
|
+
**Throws**
|
|
60
|
+
|
|
61
|
+
- `NOT_A_FILE`: if the srcPath doesn't exist or is not a file
|
|
62
|
+
|
|
63
|
+
**Example**
|
|
64
|
+
|
|
65
|
+
```ts
|
|
66
|
+
import { copyFile } from 'jg-fs';
|
|
67
|
+
|
|
68
|
+
await copyFile('config.example.json', 'config.json');
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
#### <a id="api-createDirectory"></a>`createDirectory`
|
|
72
|
+
|
|
73
|
+
*Function*
|
|
74
|
+
|
|
75
|
+
Creates a directory, with any missing parents. An existing directory is kept, or replaced with an empty one when `deleteIfExists` is set.
|
|
76
|
+
|
|
77
|
+
```ts
|
|
78
|
+
createDirectory(path: string, deleteIfExists?: boolean): Promise<void>
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
**Parameters**
|
|
82
|
+
|
|
83
|
+
- `path` `string`: The directory's path.
|
|
84
|
+
- `deleteIfExists?` `boolean`: Whether to delete an existing directory and its contents first.
|
|
85
|
+
|
|
86
|
+
**Returns** `Promise<void>`: A promise that resolves once the directory exists.
|
|
87
|
+
|
|
88
|
+
**Throws**
|
|
89
|
+
|
|
90
|
+
- `DIRECTORY_ALREADY_EXISTS`: if something other than a directory exists at the path
|
|
91
|
+
|
|
92
|
+
**Example**
|
|
93
|
+
|
|
94
|
+
```ts
|
|
95
|
+
import { createDirectory } from 'jg-fs';
|
|
96
|
+
|
|
97
|
+
await createDirectory('dist/assets'); // creates missing parents too
|
|
98
|
+
await createDirectory('dist', true); // replaces it with an empty directory
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
#### <a id="api-createDirectorySymLink"></a>`createDirectorySymLink`
|
|
102
|
+
|
|
103
|
+
*Function*
|
|
104
|
+
|
|
105
|
+
Creates a symbolic link to a directory.
|
|
106
|
+
|
|
107
|
+
```ts
|
|
108
|
+
createDirectorySymLink(target: string, path: string): Promise<void>
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
**Parameters**
|
|
112
|
+
|
|
113
|
+
- `target` `string`: The directory the link points to.
|
|
114
|
+
- `path` `string`: Where to create the link.
|
|
115
|
+
|
|
116
|
+
**Returns** `Promise<void>`: A promise that resolves once the link exists.
|
|
117
|
+
|
|
118
|
+
**Throws**
|
|
119
|
+
|
|
120
|
+
- `NON_EXISTENT_DIRECTORY`: if the target directory doesn't exist
|
|
121
|
+
- `NOT_A_DIRECTORY`: if the target directory is not considered a directory by the OS
|
|
122
|
+
|
|
123
|
+
**Example**
|
|
124
|
+
|
|
125
|
+
```ts
|
|
126
|
+
import { createDirectorySymLink } from 'jg-fs';
|
|
127
|
+
|
|
128
|
+
await createDirectorySymLink('releases/1.4.0', 'current');
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
#### <a id="api-createFileSymLink"></a>`createFileSymLink`
|
|
132
|
+
|
|
133
|
+
*Function*
|
|
134
|
+
|
|
135
|
+
Creates a symbolic link to a file.
|
|
136
|
+
|
|
137
|
+
```ts
|
|
138
|
+
createFileSymLink(target: string, path: string): Promise<void>
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
**Parameters**
|
|
142
|
+
|
|
143
|
+
- `target` `string`: The file the link points to.
|
|
144
|
+
- `path` `string`: Where to create the link.
|
|
145
|
+
|
|
146
|
+
**Returns** `Promise<void>`: A promise that resolves once the link exists.
|
|
147
|
+
|
|
148
|
+
**Throws**
|
|
149
|
+
|
|
150
|
+
- `NON_EXISTENT_FILE`: if the target file does not exist
|
|
151
|
+
- `NOT_A_FILE`: if the target is not a file
|
|
152
|
+
|
|
153
|
+
**Example**
|
|
154
|
+
|
|
155
|
+
```ts
|
|
156
|
+
import { createFileSymLink } from 'jg-fs';
|
|
157
|
+
|
|
158
|
+
await createFileSymLink('config.production.json', 'config.json');
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
#### <a id="api-deleteDirectory"></a>`deleteDirectory`
|
|
162
|
+
|
|
163
|
+
*Function*
|
|
164
|
+
|
|
165
|
+
Deletes a directory and everything in it. A missing directory is not an error.
|
|
166
|
+
|
|
167
|
+
```ts
|
|
168
|
+
deleteDirectory(path: string): Promise<void>
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
**Parameters**
|
|
172
|
+
|
|
173
|
+
- `path` `string`: The directory's path.
|
|
174
|
+
|
|
175
|
+
**Returns** `Promise<void>`: A promise that resolves once the directory is gone.
|
|
176
|
+
|
|
177
|
+
**Example**
|
|
178
|
+
|
|
179
|
+
```ts
|
|
180
|
+
import { deleteDirectory } from 'jg-fs';
|
|
181
|
+
|
|
182
|
+
await deleteDirectory('dist');
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
#### <a id="api-deleteFile"></a>`deleteFile`
|
|
186
|
+
|
|
187
|
+
*Function*
|
|
188
|
+
|
|
189
|
+
Deletes a file.
|
|
190
|
+
|
|
191
|
+
```ts
|
|
192
|
+
deleteFile(path: string): Promise<void>
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
**Parameters**
|
|
196
|
+
|
|
197
|
+
- `path` `string`: The file's path.
|
|
198
|
+
|
|
199
|
+
**Returns** `Promise<void>`: A promise that resolves once the file is gone.
|
|
200
|
+
|
|
201
|
+
**Throws**
|
|
202
|
+
|
|
203
|
+
- `NOT_A_FILE`: if the path doesn't exist or is not a file
|
|
204
|
+
|
|
205
|
+
**Example**
|
|
206
|
+
|
|
207
|
+
```ts
|
|
208
|
+
import { deleteFile } from 'jg-fs';
|
|
209
|
+
|
|
210
|
+
await deleteFile('cache.json');
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
#### <a id="api-getDirectoryElements"></a>`getDirectoryElements`
|
|
214
|
+
|
|
215
|
+
*Function*
|
|
216
|
+
|
|
217
|
+
Lists a directory's elements grouped by kind: directories, files (filtered by extension), and symbolic links, each group sorted. Entries removed while the directory is read are left out, and at most 32 entries are read at once.
|
|
218
|
+
|
|
219
|
+
```ts
|
|
220
|
+
getDirectoryElements(
|
|
221
|
+
path: string,
|
|
222
|
+
options?: Partial<IDirectoryElementsOptions>,
|
|
223
|
+
): Promise<IDirectoryPathElements>
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
**Parameters**
|
|
227
|
+
|
|
228
|
+
- `path` `string`: The directory's path.
|
|
229
|
+
- `options?` `Partial<IDirectoryElementsOptions>`: The extensions to include and how to sort.
|
|
230
|
+
|
|
231
|
+
**Returns** `Promise<IDirectoryPathElements>`: A promise that resolves to the grouped elements.
|
|
232
|
+
|
|
233
|
+
**Throws**
|
|
234
|
+
|
|
235
|
+
- `NOT_A_DIRECTORY`: if the path doesn't exist or is not a directory
|
|
236
|
+
|
|
237
|
+
**Example**
|
|
238
|
+
|
|
239
|
+
```ts
|
|
240
|
+
import { getDirectoryElements } from 'jg-fs';
|
|
241
|
+
|
|
242
|
+
const { files } = await getDirectoryElements('content', { includeExts: ['.md'], sortByKey: 'creation', sortOrder: 'desc' });
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
#### <a id="api-getPathElement"></a>`getPathElement`
|
|
246
|
+
|
|
247
|
+
*Function*
|
|
248
|
+
|
|
249
|
+
Reads a path's details without following a symbolic link at the path.
|
|
250
|
+
|
|
251
|
+
```ts
|
|
252
|
+
getPathElement(path: string): Promise<IPathElement | null>
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
**Parameters**
|
|
256
|
+
|
|
257
|
+
- `path` `string`: The path.
|
|
258
|
+
|
|
259
|
+
**Returns** `Promise<IPathElement | null>`: A promise that resolves to the path's details, or `null` when it doesn't exist.
|
|
260
|
+
|
|
261
|
+
**Example**
|
|
262
|
+
|
|
263
|
+
```ts
|
|
264
|
+
import { getPathElement } from 'jg-fs';
|
|
265
|
+
|
|
266
|
+
const element = await getPathElement('logo.png');
|
|
267
|
+
element?.size; // the size in bytes, or undefined when the path doesn't exist
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
#### <a id="api-isDirectory"></a>`isDirectory`
|
|
271
|
+
|
|
272
|
+
*Function*
|
|
273
|
+
|
|
274
|
+
Checks whether a path exists and is a directory.
|
|
275
|
+
|
|
276
|
+
```ts
|
|
277
|
+
isDirectory(path: string): Promise<boolean>
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
**Parameters**
|
|
281
|
+
|
|
282
|
+
- `path` `string`: The path.
|
|
283
|
+
|
|
284
|
+
**Returns** `Promise<boolean>`: A promise that resolves to whether the path is a directory.
|
|
285
|
+
|
|
286
|
+
**Example**
|
|
287
|
+
|
|
288
|
+
```ts
|
|
289
|
+
import { isDirectory } from 'jg-fs';
|
|
290
|
+
|
|
291
|
+
await isDirectory('dist'); // true
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
#### <a id="api-isFile"></a>`isFile`
|
|
295
|
+
|
|
296
|
+
*Function*
|
|
297
|
+
|
|
298
|
+
Checks whether a path exists and is a regular file.
|
|
299
|
+
|
|
300
|
+
```ts
|
|
301
|
+
isFile(path: string): Promise<boolean>
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
**Parameters**
|
|
305
|
+
|
|
306
|
+
- `path` `string`: The path.
|
|
307
|
+
|
|
308
|
+
**Returns** `Promise<boolean>`: A promise that resolves to whether the path is a file.
|
|
309
|
+
|
|
310
|
+
**Example**
|
|
311
|
+
|
|
312
|
+
```ts
|
|
313
|
+
import { isFile } from 'jg-fs';
|
|
314
|
+
|
|
315
|
+
await isFile('package.json'); // true
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
#### <a id="api-isPathWithin"></a>`isPathWithin`
|
|
319
|
+
|
|
320
|
+
*Function*
|
|
321
|
+
|
|
322
|
+
Checks whether a path is a root path or nested inside it. The check is lexical: both paths are resolved without touching the filesystem, and symbolic links aren't followed. Sibling paths that share a prefix, such as `/data/app` and `/data/application`, aren't nested, and neither is a path on another drive on Windows.
|
|
323
|
+
|
|
324
|
+
```ts
|
|
325
|
+
isPathWithin(rootPath: string, targetPath: string): boolean
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
**Parameters**
|
|
329
|
+
|
|
330
|
+
- `rootPath` `string`: The root path.
|
|
331
|
+
- `targetPath` `string`: The path to check.
|
|
332
|
+
|
|
333
|
+
**Returns** `boolean`: Whether the target is the root or inside it.
|
|
334
|
+
|
|
335
|
+
**Example**
|
|
336
|
+
|
|
337
|
+
```ts
|
|
338
|
+
import { isPathWithin } from 'jg-fs';
|
|
339
|
+
|
|
340
|
+
isPathWithin('/data/app', '/data/app/logs/today.log'); // true
|
|
341
|
+
isPathWithin('/data/app', '/data/app/../secrets'); // false
|
|
342
|
+
isPathWithin('/data/app', '/data/application'); // false
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
#### <a id="api-pathExists"></a>`pathExists`
|
|
346
|
+
|
|
347
|
+
*Function*
|
|
348
|
+
|
|
349
|
+
Checks whether a path exists, whether it's a file, a directory, or anything else.
|
|
350
|
+
|
|
351
|
+
```ts
|
|
352
|
+
pathExists(path: string): Promise<boolean>
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
**Parameters**
|
|
356
|
+
|
|
357
|
+
- `path` `string`: The path.
|
|
358
|
+
|
|
359
|
+
**Returns** `Promise<boolean>`: A promise that resolves to whether the path exists.
|
|
360
|
+
|
|
361
|
+
**Example**
|
|
362
|
+
|
|
363
|
+
```ts
|
|
364
|
+
import { pathExists } from 'jg-fs';
|
|
365
|
+
|
|
366
|
+
await pathExists('config.json'); // true when the file exists
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
#### <a id="api-readBoundedFile"></a>`readBoundedFile`
|
|
370
|
+
|
|
371
|
+
*Function*
|
|
372
|
+
|
|
373
|
+
Reads a regular file of at most `maxBytes` bytes. It never follows a symbolic link in the path's last component, though links in parent directories are followed, so callers that need containment combine it with `isPathWithin`. It reads at most `maxBytes + 1` bytes, even when the file grows while it's read.
|
|
374
|
+
|
|
375
|
+
```ts
|
|
376
|
+
readBoundedFile(
|
|
377
|
+
path: string,
|
|
378
|
+
maxBytes: number,
|
|
379
|
+
): Promise<Buffer<ArrayBufferLike>>
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
**Parameters**
|
|
383
|
+
|
|
384
|
+
- `path` `string`: The file's path.
|
|
385
|
+
- `maxBytes` `number`: The largest size accepted, in bytes.
|
|
386
|
+
|
|
387
|
+
**Returns** `Promise<Buffer<ArrayBufferLike>>`: A promise that resolves to the content.
|
|
388
|
+
|
|
389
|
+
**Throws**
|
|
390
|
+
|
|
391
|
+
- `NOT_A_FILE`: if the path doesn't exist, its final component is a symbolic link, or it isn't a regular file
|
|
392
|
+
- `FILE_TOO_LARGE`: if the file holds more than maxBytes bytes
|
|
393
|
+
|
|
394
|
+
**Example**
|
|
395
|
+
|
|
396
|
+
```ts
|
|
397
|
+
import { join } from 'node:path';
|
|
398
|
+
import { readBoundedFile } from 'jg-fs';
|
|
399
|
+
|
|
400
|
+
const upload = await readBoundedFile(join('uploads', 'avatar.png'), 5 * 1024 * 1024); // at most 5 MB
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
#### <a id="api-readBufferFile"></a>`readBufferFile`
|
|
404
|
+
|
|
405
|
+
*Function*
|
|
406
|
+
|
|
407
|
+
Reads a binary file. An empty file reads as an empty Buffer.
|
|
408
|
+
|
|
409
|
+
```ts
|
|
410
|
+
readBufferFile(path: string): Promise<Buffer<ArrayBufferLike>>
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
**Parameters**
|
|
414
|
+
|
|
415
|
+
- `path` `string`: The file's path.
|
|
416
|
+
|
|
417
|
+
**Returns** `Promise<Buffer<ArrayBufferLike>>`: A promise that resolves to the content.
|
|
418
|
+
|
|
419
|
+
**Throws**
|
|
420
|
+
|
|
421
|
+
- `NOT_A_FILE`: if the path doesn't exist or is not a file
|
|
422
|
+
|
|
423
|
+
**Example**
|
|
424
|
+
|
|
425
|
+
```ts
|
|
426
|
+
import { readBufferFile } from 'jg-fs';
|
|
427
|
+
|
|
428
|
+
const image = await readBufferFile('avatar.png');
|
|
429
|
+
```
|
|
430
|
+
|
|
431
|
+
#### <a id="api-readDirectory"></a>`readDirectory`
|
|
432
|
+
|
|
433
|
+
*Function*
|
|
434
|
+
|
|
435
|
+
Lists a directory's contents as paths joined to the directory's path.
|
|
436
|
+
|
|
437
|
+
```ts
|
|
438
|
+
readDirectory(path: string, recursive?: boolean): Promise<string[]>
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
**Parameters**
|
|
442
|
+
|
|
443
|
+
- `path` `string`: The directory's path.
|
|
444
|
+
- `recursive?` `boolean`: Whether to include the contents of subdirectories. Defaults to `false`.
|
|
445
|
+
|
|
446
|
+
**Returns** `Promise<string[]>`: A promise that resolves to the content paths.
|
|
447
|
+
|
|
448
|
+
**Throws**
|
|
449
|
+
|
|
450
|
+
- `NOT_A_DIRECTORY`: if the path doesn't exist or is not a directory
|
|
451
|
+
|
|
452
|
+
**Example**
|
|
453
|
+
|
|
454
|
+
```ts
|
|
455
|
+
import { readDirectory } from 'jg-fs';
|
|
456
|
+
|
|
457
|
+
await readDirectory('dist'); // ['dist/index.js', 'dist/assets']
|
|
458
|
+
await readDirectory('dist', true); // includes the contents of dist/assets
|
|
459
|
+
```
|
|
460
|
+
|
|
461
|
+
#### <a id="api-readFile"></a>`readFile`
|
|
462
|
+
|
|
463
|
+
*Function*
|
|
464
|
+
|
|
465
|
+
Reads a file as a string when an encoding is given, or as a Buffer otherwise.
|
|
466
|
+
|
|
467
|
+
```ts
|
|
468
|
+
readFile(path: string, options: IReadStringFileOptions): Promise<string>
|
|
469
|
+
```
|
|
470
|
+
|
|
471
|
+
**Parameters**
|
|
472
|
+
|
|
473
|
+
- `path` `string`: The file's path.
|
|
474
|
+
- `options` `IReadStringFileOptions`: Node.js's readFile options, such as the encoding.
|
|
475
|
+
|
|
476
|
+
**Returns** `Promise<string>`: A promise that resolves to the content.
|
|
477
|
+
|
|
478
|
+
**Throws**
|
|
479
|
+
|
|
480
|
+
- `NOT_A_FILE`: if the path doesn't exist or is not a file
|
|
481
|
+
|
|
482
|
+
```ts
|
|
483
|
+
readFile(
|
|
484
|
+
path: string,
|
|
485
|
+
options?: IReadBufferFileOptions,
|
|
486
|
+
): Promise<Buffer<ArrayBufferLike>>
|
|
487
|
+
```
|
|
488
|
+
|
|
489
|
+
**Parameters**
|
|
490
|
+
|
|
491
|
+
- `path` `string`: The file's path.
|
|
492
|
+
- `options?` `IReadBufferFileOptions`: Node.js's readFile options, such as the encoding.
|
|
493
|
+
|
|
494
|
+
**Returns** `Promise<Buffer<ArrayBufferLike>>`: A promise that resolves to the content.
|
|
495
|
+
|
|
496
|
+
**Throws**
|
|
497
|
+
|
|
498
|
+
- `NOT_A_FILE`: if the path doesn't exist or is not a file
|
|
499
|
+
|
|
500
|
+
```ts
|
|
501
|
+
readFile(
|
|
502
|
+
path: string,
|
|
503
|
+
options?: IReadFileOptions,
|
|
504
|
+
): Promise<string | Buffer<ArrayBufferLike>>
|
|
505
|
+
```
|
|
506
|
+
|
|
507
|
+
**Parameters**
|
|
508
|
+
|
|
509
|
+
- `path` `string`: The file's path.
|
|
510
|
+
- `options?` `IReadFileOptions`: Node.js's readFile options, such as the encoding.
|
|
511
|
+
|
|
512
|
+
**Returns** `Promise<string | Buffer<ArrayBufferLike>>`: A promise that resolves to the content.
|
|
513
|
+
|
|
514
|
+
**Throws**
|
|
515
|
+
|
|
516
|
+
- `NOT_A_FILE`: if the path doesn't exist or is not a file
|
|
517
|
+
|
|
518
|
+
**Example**
|
|
519
|
+
|
|
520
|
+
```ts
|
|
521
|
+
import { readFile } from 'jg-fs';
|
|
522
|
+
|
|
523
|
+
await readFile('notes.md', 'utf-8'); // a string
|
|
524
|
+
await readFile('avatar.png'); // a Buffer
|
|
525
|
+
```
|
|
526
|
+
|
|
527
|
+
#### <a id="api-readJsonFile"></a>`readJsonFile`
|
|
528
|
+
|
|
529
|
+
*Function*
|
|
530
|
+
|
|
531
|
+
Reads and parses a JSON file, and validates it with the schema when there is one. Without a schema, the value is `unknown`, or the type you pass.
|
|
532
|
+
|
|
533
|
+
```ts
|
|
534
|
+
readJsonFile<T = unknown>(
|
|
535
|
+
path: string,
|
|
536
|
+
options?: IReadJsonFileOptions<T>,
|
|
537
|
+
): Promise<T>
|
|
538
|
+
```
|
|
539
|
+
|
|
540
|
+
**Parameters**
|
|
541
|
+
|
|
542
|
+
- `path` `string`: The file's path.
|
|
543
|
+
- `options?` `IReadJsonFileOptions<T>`: The schema, such as a Zod schema, whose errors propagate unchanged. Defaults to `{}`.
|
|
544
|
+
|
|
545
|
+
**Returns** `Promise<T>`: A promise that resolves to the parsed value.
|
|
546
|
+
|
|
547
|
+
**Throws**
|
|
548
|
+
|
|
549
|
+
- `NOT_A_FILE`: if the path doesn't exist or is not a file
|
|
550
|
+
- `FILE_CONTENT_IS_EMPTY_OR_INVALID`: if the file's JSON content cannot be parsed
|
|
551
|
+
|
|
552
|
+
**Example 1**
|
|
553
|
+
|
|
554
|
+
```ts
|
|
555
|
+
import { readJsonFile } from 'jg-fs';
|
|
556
|
+
|
|
557
|
+
const config = await readJsonFile('config.json', { schema: Config }); // Config's type
|
|
558
|
+
```
|
|
559
|
+
|
|
560
|
+
**Example 2**
|
|
561
|
+
|
|
562
|
+
```ts
|
|
563
|
+
import { readJsonFile } from 'jg-fs';
|
|
564
|
+
|
|
565
|
+
const value = await readJsonFile('data.json'); // unknown
|
|
566
|
+
```
|
|
567
|
+
|
|
568
|
+
#### <a id="api-readTextFile"></a>`readTextFile`
|
|
569
|
+
|
|
570
|
+
*Function*
|
|
571
|
+
|
|
572
|
+
Reads a UTF-8 text file. An empty file reads as an empty string.
|
|
573
|
+
|
|
574
|
+
```ts
|
|
575
|
+
readTextFile(path: string): Promise<string>
|
|
576
|
+
```
|
|
577
|
+
|
|
578
|
+
**Parameters**
|
|
579
|
+
|
|
580
|
+
- `path` `string`: The file's path.
|
|
581
|
+
|
|
582
|
+
**Returns** `Promise<string>`: A promise that resolves to the text.
|
|
583
|
+
|
|
584
|
+
**Throws**
|
|
585
|
+
|
|
586
|
+
- `NOT_A_FILE`: if the path doesn't exist or is not a file
|
|
587
|
+
|
|
588
|
+
**Example**
|
|
589
|
+
|
|
590
|
+
```ts
|
|
591
|
+
import { readTextFile } from 'jg-fs';
|
|
592
|
+
|
|
593
|
+
const markdown = await readTextFile('README.md');
|
|
594
|
+
```
|
|
595
|
+
|
|
596
|
+
#### <a id="api-writeBufferFile"></a>`writeBufferFile`
|
|
597
|
+
|
|
598
|
+
*Function*
|
|
599
|
+
|
|
600
|
+
Writes a binary file. An empty Buffer writes an empty file.
|
|
601
|
+
|
|
602
|
+
```ts
|
|
603
|
+
writeBufferFile(path: string, data: Buffer): Promise<void>
|
|
604
|
+
```
|
|
605
|
+
|
|
606
|
+
**Parameters**
|
|
607
|
+
|
|
608
|
+
- `path` `string`: The file's path.
|
|
609
|
+
- `data` `Buffer`: The content.
|
|
610
|
+
|
|
611
|
+
**Returns** `Promise<void>`: A promise that resolves once the file is written.
|
|
612
|
+
|
|
613
|
+
**Throws**
|
|
614
|
+
|
|
615
|
+
- `FILE_CONTENT_IS_EMPTY_OR_INVALID`: if the data isn't a Buffer
|
|
616
|
+
|
|
617
|
+
**Example**
|
|
618
|
+
|
|
619
|
+
```ts
|
|
620
|
+
import { writeBufferFile } from 'jg-fs';
|
|
621
|
+
|
|
622
|
+
const imageBuffer = Buffer.from('iVBORw0KGgo=', 'base64');
|
|
623
|
+
await writeBufferFile('avatar.png', imageBuffer);
|
|
624
|
+
```
|
|
625
|
+
|
|
626
|
+
#### <a id="api-writeFile"></a>`writeFile`
|
|
627
|
+
|
|
628
|
+
*Function*
|
|
629
|
+
|
|
630
|
+
Writes a file, creating its directory first when it doesn't exist.
|
|
631
|
+
|
|
632
|
+
```ts
|
|
633
|
+
writeFile(
|
|
634
|
+
path: string,
|
|
635
|
+
data: string | ArrayBufferView<ArrayBufferLike>,
|
|
636
|
+
options?: WriteFileOptions,
|
|
637
|
+
): Promise<void>
|
|
638
|
+
```
|
|
639
|
+
|
|
640
|
+
**Parameters**
|
|
641
|
+
|
|
642
|
+
- `path` `string`: The file's path.
|
|
643
|
+
- `data` `string | ArrayBufferView<ArrayBufferLike>`: The content.
|
|
644
|
+
- `options?` `WriteFileOptions`: Node.js's writeFile options, such as the encoding or mode.
|
|
645
|
+
|
|
646
|
+
**Returns** `Promise<void>`: A promise that resolves once the file is written.
|
|
647
|
+
|
|
648
|
+
**Example**
|
|
649
|
+
|
|
650
|
+
```ts
|
|
651
|
+
import { writeFile } from 'jg-fs';
|
|
652
|
+
|
|
653
|
+
const csv = 'id,name\n1,Ada\n';
|
|
654
|
+
await writeFile('out/report.csv', csv, { encoding: 'utf-8' });
|
|
655
|
+
```
|
|
656
|
+
|
|
657
|
+
#### <a id="api-writeFileAtomic"></a>`writeFileAtomic`
|
|
658
|
+
|
|
659
|
+
*Function*
|
|
660
|
+
|
|
661
|
+
Writes a file atomically: readers see either the previous content or the complete new content, never a partial write. The data goes to a temporary file in the same directory, which is flushed to disk and renamed over the path; on POSIX, the directory is flushed too. An explicit mode wins; without one, a replaced file keeps its permission bits and a new file gets the platform default. The temporary file is never more widely readable than the final mode. When writing fails before the rename, the temporary file is removed and the destination is untouched.
|
|
662
|
+
|
|
663
|
+
```ts
|
|
664
|
+
writeFileAtomic(
|
|
665
|
+
path: string,
|
|
666
|
+
data: string | ArrayBufferView<ArrayBufferLike>,
|
|
667
|
+
mode?: number,
|
|
668
|
+
): Promise<void>
|
|
669
|
+
```
|
|
670
|
+
|
|
671
|
+
**Parameters**
|
|
672
|
+
|
|
673
|
+
- `path` `string`: The file's path.
|
|
674
|
+
- `data` `string | ArrayBufferView<ArrayBufferLike>`: The content.
|
|
675
|
+
- `mode?` `number`: The permission bits of the written file, such as `0o600`.
|
|
676
|
+
|
|
677
|
+
**Returns** `Promise<void>`: A promise that resolves once the file is written and flushed.
|
|
678
|
+
|
|
679
|
+
**Example**
|
|
680
|
+
|
|
681
|
+
```ts
|
|
682
|
+
import { writeFileAtomic } from 'jg-fs';
|
|
683
|
+
|
|
684
|
+
const state = { step: 2 };
|
|
685
|
+
await writeFileAtomic('state.json', JSON.stringify(state)); // readers never see a partial file
|
|
686
|
+
await writeFileAtomic('secrets.env', 'TOKEN=abc\n', 0o600); // only the owner can read it
|
|
687
|
+
```
|
|
688
|
+
|
|
689
|
+
#### <a id="api-writeJsonFile"></a>`writeJsonFile`
|
|
690
|
+
|
|
691
|
+
*Function*
|
|
692
|
+
|
|
693
|
+
Writes a JSON file. A string is written as given; anything else is stringified.
|
|
694
|
+
|
|
695
|
+
```ts
|
|
696
|
+
writeJsonFile<T = Record<string, unknown>>(
|
|
697
|
+
path: string,
|
|
698
|
+
data: string | T,
|
|
699
|
+
space?: number,
|
|
700
|
+
): Promise<void>
|
|
701
|
+
```
|
|
702
|
+
|
|
703
|
+
**Parameters**
|
|
704
|
+
|
|
705
|
+
- `path` `string`: The file's path.
|
|
706
|
+
- `data` `string | T`: The value, or its JSON text.
|
|
707
|
+
- `space?` `number`: The indentation for stringified values. Defaults to `2`.
|
|
708
|
+
|
|
709
|
+
**Returns** `Promise<void>`: A promise that resolves once the file is written.
|
|
710
|
+
|
|
711
|
+
**Throws**
|
|
712
|
+
|
|
713
|
+
- `FILE_CONTENT_IS_EMPTY_OR_INVALID`: if the JSON content cannot be stringified or is empty
|
|
714
|
+
|
|
715
|
+
**Example**
|
|
716
|
+
|
|
717
|
+
```ts
|
|
718
|
+
import { writeJsonFile } from 'jg-fs';
|
|
719
|
+
|
|
720
|
+
await writeJsonFile('config.json', { port: 8080 });
|
|
721
|
+
```
|
|
722
|
+
|
|
723
|
+
#### <a id="api-writeTextFile"></a>`writeTextFile`
|
|
724
|
+
|
|
725
|
+
*Function*
|
|
726
|
+
|
|
727
|
+
Writes a UTF-8 text file. An empty string writes an empty file.
|
|
728
|
+
|
|
729
|
+
```ts
|
|
730
|
+
writeTextFile(path: string, data: string): Promise<void>
|
|
731
|
+
```
|
|
732
|
+
|
|
733
|
+
**Parameters**
|
|
734
|
+
|
|
735
|
+
- `path` `string`: The file's path.
|
|
736
|
+
- `data` `string`: The text.
|
|
737
|
+
|
|
738
|
+
**Returns** `Promise<void>`: A promise that resolves once the file is written.
|
|
739
|
+
|
|
740
|
+
**Throws**
|
|
741
|
+
|
|
742
|
+
- `FILE_CONTENT_IS_EMPTY_OR_INVALID`: if the data isn't a string
|
|
743
|
+
|
|
744
|
+
**Example**
|
|
745
|
+
|
|
746
|
+
```ts
|
|
747
|
+
import { writeTextFile } from 'jg-fs';
|
|
748
|
+
|
|
749
|
+
await writeTextFile('notes/today.md', '# Today');
|
|
750
|
+
```
|
|
751
|
+
|
|
752
|
+
### <a id="api-constants"></a>Constants in `jg-fs`
|
|
753
|
+
|
|
754
|
+
#### <a id="api-ERRORS"></a>`ERRORS`
|
|
755
|
+
|
|
756
|
+
*Constant*
|
|
757
|
+
|
|
758
|
+
the codes of every error the package throws, from both the async and the sync entry
|
|
759
|
+
|
|
760
|
+
```ts
|
|
761
|
+
const ERRORS: { NOT_A_DIRECTORY: "NOT_A_DIRECTORY"; NON_EXISTENT_DIRECTORY: "NON_EXISTENT_DIRECTORY"; DIRECTORY_ALREADY_EXISTS: "DIRECTORY_ALREADY_EXISTS"; NON_EXISTENT_FILE: "NON_EXISTENT_FILE"; NOT_A_FILE: "NOT_A_FILE"; FILE_CONTENT_IS_EMPTY_OR_INVALID: "FILE_CONTENT_IS_EMPTY_OR_INVALID"; FILE_TOO_LARGE: "FILE_TOO_LARGE" }
|
|
762
|
+
```
|
|
763
|
+
|
|
764
|
+
### <a id="api-types"></a>Types in `jg-fs`
|
|
765
|
+
|
|
766
|
+
#### <a id="api-IDirectoryElementsKeySort"></a>`IDirectoryElementsKeySort`
|
|
767
|
+
|
|
768
|
+
*Type*
|
|
769
|
+
|
|
770
|
+
the keys a directory's elements can be sorted by
|
|
771
|
+
|
|
772
|
+
```ts
|
|
773
|
+
type IDirectoryElementsKeySort = 'baseName' | 'size' | 'creation';
|
|
774
|
+
```
|
|
775
|
+
|
|
776
|
+
#### <a id="api-IDirectoryElementsOptions"></a>`IDirectoryElementsOptions`
|
|
777
|
+
|
|
778
|
+
*Type*
|
|
779
|
+
|
|
780
|
+
how getDirectoryElements filters and sorts a directory's elements
|
|
781
|
+
|
|
782
|
+
```ts
|
|
783
|
+
type IDirectoryElementsOptions = {
|
|
784
|
+
sortByKey: IDirectoryElementsKeySort;
|
|
785
|
+
sortOrder: ISortDirection;
|
|
786
|
+
includeExts: string[];
|
|
787
|
+
};
|
|
788
|
+
```
|
|
789
|
+
|
|
790
|
+
**Members**
|
|
791
|
+
|
|
792
|
+
- `sortByKey: IDirectoryElementsKeySort` (property): the key the elements are sorted by. Defaults to 'baseName'
|
|
793
|
+
- `sortOrder: ISortDirection` (property): the sort direction. Defaults to 'asc'
|
|
794
|
+
- `includeExts: string[]` (property): the extensions of the files to include, such as ['.json'], matched case-insensitively. Defaults to all
|
|
795
|
+
|
|
796
|
+
#### <a id="api-IDirectoryPathElements"></a>`IDirectoryPathElements`
|
|
797
|
+
|
|
798
|
+
*Type*
|
|
799
|
+
|
|
800
|
+
a directory's elements, grouped by kind
|
|
801
|
+
|
|
802
|
+
```ts
|
|
803
|
+
type IDirectoryPathElements = {
|
|
804
|
+
directories: IPathElement[];
|
|
805
|
+
files: IPathElement[];
|
|
806
|
+
symbolicLinks: IPathElement[];
|
|
807
|
+
};
|
|
808
|
+
```
|
|
809
|
+
|
|
810
|
+
**Members**
|
|
811
|
+
|
|
812
|
+
- `directories: IPathElement[]` (property)
|
|
813
|
+
- `files: IPathElement[]` (property)
|
|
814
|
+
- `symbolicLinks: IPathElement[]` (property)
|
|
815
|
+
|
|
816
|
+
#### <a id="api-IPathElement"></a>`IPathElement`
|
|
817
|
+
|
|
818
|
+
*Type*
|
|
819
|
+
|
|
820
|
+
the details of a path, read with lstat, so a symbolic link is described rather than followed
|
|
821
|
+
|
|
822
|
+
```ts
|
|
823
|
+
type IPathElement = {
|
|
824
|
+
path: string;
|
|
825
|
+
baseName: string;
|
|
826
|
+
extName: string;
|
|
827
|
+
isFile: boolean;
|
|
828
|
+
isDirectory: boolean;
|
|
829
|
+
isSymbolicLink: boolean;
|
|
830
|
+
size: number;
|
|
831
|
+
creation: number;
|
|
832
|
+
};
|
|
833
|
+
```
|
|
834
|
+
|
|
835
|
+
**Members**
|
|
836
|
+
|
|
837
|
+
- `path: string` (property): the path, as given
|
|
838
|
+
- `baseName: string` (property): the last segment of the path
|
|
839
|
+
- `extName: string` (property): the extension, such as '.json', or an empty string when there is none
|
|
840
|
+
- `isFile: boolean` (property): whether it's a regular file
|
|
841
|
+
- `isDirectory: boolean` (property): whether it's a directory
|
|
842
|
+
- `isSymbolicLink: boolean` (property): whether it's a symbolic link, in which case isFile and isDirectory are false
|
|
843
|
+
- `size: number` (property): the size in bytes
|
|
844
|
+
- `creation: number` (property): when it was created, in milliseconds since the epoch
|
|
845
|
+
|
|
846
|
+
#### <a id="api-IReadJsonFileOptions"></a>`IReadJsonFileOptions`
|
|
847
|
+
|
|
848
|
+
*Type*
|
|
849
|
+
|
|
850
|
+
what readJsonFile accepts
|
|
851
|
+
|
|
852
|
+
```ts
|
|
853
|
+
type IReadJsonFileOptions<T> = {
|
|
854
|
+
schema?: ISchema<T>;
|
|
855
|
+
};
|
|
856
|
+
```
|
|
857
|
+
|
|
858
|
+
**Members**
|
|
859
|
+
|
|
860
|
+
- `schema: ISchema<T>` (property): validates the parsed content, such as a Zod schema. Its errors propagate unchanged
|
|
861
|
+
|
|
862
|
+
#### <a id="api-ISchema"></a>`ISchema`
|
|
863
|
+
|
|
864
|
+
*Type*
|
|
865
|
+
|
|
866
|
+
validates parsed data and returns it typed, which a Zod schema does
|
|
867
|
+
|
|
868
|
+
```ts
|
|
869
|
+
type ISchema<T> = {
|
|
870
|
+
parse(value: unknown): T;
|
|
871
|
+
};
|
|
872
|
+
```
|
|
873
|
+
|
|
874
|
+
**Members**
|
|
875
|
+
|
|
876
|
+
- `parse(value: unknown): T` (method)
|
|
877
|
+
|
|
878
|
+
## <a id="api-entry-sync"></a>`jg-fs/sync`
|
|
879
|
+
|
|
880
|
+
- Functions: [`copyDirectory`](#api-sync-copyDirectory), [`copyFile`](#api-sync-copyFile), [`createDirectory`](#api-sync-createDirectory), [`createDirectorySymLink`](#api-sync-createDirectorySymLink), [`createFileSymLink`](#api-sync-createFileSymLink), [`deleteDirectory`](#api-sync-deleteDirectory), [`deleteFile`](#api-sync-deleteFile), [`getDirectoryElements`](#api-sync-getDirectoryElements), [`getPathElement`](#api-sync-getPathElement), [`isDirectory`](#api-sync-isDirectory), [`isFile`](#api-sync-isFile), [`isPathWithin`](#api-sync-isPathWithin), [`pathExists`](#api-sync-pathExists), [`readBoundedFile`](#api-sync-readBoundedFile), [`readBufferFile`](#api-sync-readBufferFile), [`readDirectory`](#api-sync-readDirectory), [`readFile`](#api-sync-readFile), [`readJsonFile`](#api-sync-readJsonFile), [`readTextFile`](#api-sync-readTextFile), [`writeBufferFile`](#api-sync-writeBufferFile), [`writeFile`](#api-sync-writeFile), [`writeFileAtomic`](#api-sync-writeFileAtomic), [`writeJsonFile`](#api-sync-writeJsonFile), [`writeTextFile`](#api-sync-writeTextFile)
|
|
881
|
+
- Constants: [`ERRORS`](#api-sync-ERRORS)
|
|
882
|
+
- Types: [`IDirectoryElementsKeySort`](#api-sync-IDirectoryElementsKeySort), [`IDirectoryElementsOptions`](#api-sync-IDirectoryElementsOptions), [`IDirectoryPathElements`](#api-sync-IDirectoryPathElements), [`IPathElement`](#api-sync-IPathElement), [`IReadJsonFileOptions`](#api-sync-IReadJsonFileOptions), [`ISchema`](#api-sync-ISchema)
|
|
883
|
+
|
|
884
|
+
### <a id="api-sync-functions"></a>Functions in `jg-fs/sync`
|
|
885
|
+
|
|
886
|
+
#### <a id="api-sync-copyDirectory"></a>`copyDirectory`
|
|
887
|
+
|
|
888
|
+
*Function*
|
|
889
|
+
|
|
890
|
+
Copies a directory and everything in it, replacing the destination completely.
|
|
891
|
+
|
|
892
|
+
```ts
|
|
893
|
+
copyDirectory(srcPath: string, destPath: string): void
|
|
894
|
+
```
|
|
895
|
+
|
|
896
|
+
**Parameters**
|
|
897
|
+
|
|
898
|
+
- `srcPath` `string`: The directory to copy.
|
|
899
|
+
- `destPath` `string`: Where to copy it.
|
|
900
|
+
|
|
901
|
+
**Throws**
|
|
902
|
+
|
|
903
|
+
- `NOT_A_DIRECTORY`: if the srcPath is not a directory
|
|
904
|
+
|
|
905
|
+
**Example**
|
|
906
|
+
|
|
907
|
+
```ts
|
|
908
|
+
import { copyDirectory } from 'jg-fs/sync';
|
|
909
|
+
|
|
910
|
+
copyDirectory('templates', 'dist/templates');
|
|
911
|
+
```
|
|
912
|
+
|
|
913
|
+
#### <a id="api-sync-copyFile"></a>`copyFile`
|
|
914
|
+
|
|
915
|
+
*Function*
|
|
916
|
+
|
|
917
|
+
Copies a file, replacing the destination when it exists.
|
|
918
|
+
|
|
919
|
+
```ts
|
|
920
|
+
copyFile(srcPath: string, destPath: string): void
|
|
921
|
+
```
|
|
922
|
+
|
|
923
|
+
**Parameters**
|
|
924
|
+
|
|
925
|
+
- `srcPath` `string`: The file to copy.
|
|
926
|
+
- `destPath` `string`: Where to copy it.
|
|
927
|
+
|
|
928
|
+
**Throws**
|
|
929
|
+
|
|
930
|
+
- `NOT_A_FILE`: if the srcPath doesn't exist or is not a file
|
|
931
|
+
|
|
932
|
+
**Example**
|
|
933
|
+
|
|
934
|
+
```ts
|
|
935
|
+
import { copyFile } from 'jg-fs/sync';
|
|
936
|
+
|
|
937
|
+
copyFile('config.example.json', 'config.json');
|
|
938
|
+
```
|
|
939
|
+
|
|
940
|
+
#### <a id="api-sync-createDirectory"></a>`createDirectory`
|
|
941
|
+
|
|
942
|
+
*Function*
|
|
943
|
+
|
|
944
|
+
Creates a directory, with any missing parents. An existing directory is kept, or replaced with an empty one when `deleteIfExists` is set.
|
|
945
|
+
|
|
946
|
+
```ts
|
|
947
|
+
createDirectory(path: string, deleteIfExists?: boolean): void
|
|
948
|
+
```
|
|
949
|
+
|
|
950
|
+
**Parameters**
|
|
951
|
+
|
|
952
|
+
- `path` `string`: The directory's path.
|
|
953
|
+
- `deleteIfExists?` `boolean`: Whether to delete an existing directory and its contents first.
|
|
954
|
+
|
|
955
|
+
**Throws**
|
|
956
|
+
|
|
957
|
+
- `DIRECTORY_ALREADY_EXISTS`: if something other than a directory exists at the path
|
|
958
|
+
|
|
959
|
+
**Example**
|
|
960
|
+
|
|
961
|
+
```ts
|
|
962
|
+
import { createDirectory } from 'jg-fs/sync';
|
|
963
|
+
|
|
964
|
+
createDirectory('dist/assets'); // creates missing parents too
|
|
965
|
+
createDirectory('dist', true); // replaces it with an empty directory
|
|
966
|
+
```
|
|
967
|
+
|
|
968
|
+
#### <a id="api-sync-createDirectorySymLink"></a>`createDirectorySymLink`
|
|
969
|
+
|
|
970
|
+
*Function*
|
|
971
|
+
|
|
972
|
+
Creates a symbolic link to a directory.
|
|
973
|
+
|
|
974
|
+
```ts
|
|
975
|
+
createDirectorySymLink(target: string, path: string): void
|
|
976
|
+
```
|
|
977
|
+
|
|
978
|
+
**Parameters**
|
|
979
|
+
|
|
980
|
+
- `target` `string`: The directory the link points to.
|
|
981
|
+
- `path` `string`: Where to create the link.
|
|
982
|
+
|
|
983
|
+
**Throws**
|
|
984
|
+
|
|
985
|
+
- `NON_EXISTENT_DIRECTORY`: if the target directory doesn't exist
|
|
986
|
+
- `NOT_A_DIRECTORY`: if the target directory is not considered a directory by the OS
|
|
987
|
+
|
|
988
|
+
**Example**
|
|
989
|
+
|
|
990
|
+
```ts
|
|
991
|
+
import { createDirectorySymLink } from 'jg-fs/sync';
|
|
992
|
+
|
|
993
|
+
createDirectorySymLink('releases/1.4.0', 'current');
|
|
994
|
+
```
|
|
995
|
+
|
|
996
|
+
#### <a id="api-sync-createFileSymLink"></a>`createFileSymLink`
|
|
997
|
+
|
|
998
|
+
*Function*
|
|
999
|
+
|
|
1000
|
+
Creates a symbolic link to a file.
|
|
1001
|
+
|
|
1002
|
+
```ts
|
|
1003
|
+
createFileSymLink(target: string, path: string): void
|
|
1004
|
+
```
|
|
1005
|
+
|
|
1006
|
+
**Parameters**
|
|
1007
|
+
|
|
1008
|
+
- `target` `string`: The file the link points to.
|
|
1009
|
+
- `path` `string`: Where to create the link.
|
|
1010
|
+
|
|
1011
|
+
**Throws**
|
|
1012
|
+
|
|
1013
|
+
- `NON_EXISTENT_FILE`: if the target file does not exist
|
|
1014
|
+
- `NOT_A_FILE`: if the target is not a file
|
|
1015
|
+
|
|
1016
|
+
**Example**
|
|
1017
|
+
|
|
1018
|
+
```ts
|
|
1019
|
+
import { createFileSymLink } from 'jg-fs/sync';
|
|
1020
|
+
|
|
1021
|
+
createFileSymLink('config.production.json', 'config.json');
|
|
1022
|
+
```
|
|
1023
|
+
|
|
1024
|
+
#### <a id="api-sync-deleteDirectory"></a>`deleteDirectory`
|
|
1025
|
+
|
|
1026
|
+
*Function*
|
|
1027
|
+
|
|
1028
|
+
Deletes a directory and everything in it. A missing directory is not an error.
|
|
1029
|
+
|
|
1030
|
+
```ts
|
|
1031
|
+
deleteDirectory(path: string): void
|
|
1032
|
+
```
|
|
1033
|
+
|
|
1034
|
+
**Parameters**
|
|
1035
|
+
|
|
1036
|
+
- `path` `string`: The directory's path.
|
|
1037
|
+
|
|
1038
|
+
**Example**
|
|
1039
|
+
|
|
1040
|
+
```ts
|
|
1041
|
+
import { deleteDirectory } from 'jg-fs/sync';
|
|
1042
|
+
|
|
1043
|
+
deleteDirectory('dist');
|
|
1044
|
+
```
|
|
1045
|
+
|
|
1046
|
+
#### <a id="api-sync-deleteFile"></a>`deleteFile`
|
|
1047
|
+
|
|
1048
|
+
*Function*
|
|
1049
|
+
|
|
1050
|
+
Deletes a file.
|
|
1051
|
+
|
|
1052
|
+
```ts
|
|
1053
|
+
deleteFile(path: string): void
|
|
1054
|
+
```
|
|
1055
|
+
|
|
1056
|
+
**Parameters**
|
|
1057
|
+
|
|
1058
|
+
- `path` `string`: The file's path.
|
|
1059
|
+
|
|
1060
|
+
**Throws**
|
|
1061
|
+
|
|
1062
|
+
- `NOT_A_FILE`: if the path doesn't exist or is not a file
|
|
1063
|
+
|
|
1064
|
+
**Example**
|
|
1065
|
+
|
|
1066
|
+
```ts
|
|
1067
|
+
import { deleteFile } from 'jg-fs/sync';
|
|
1068
|
+
|
|
1069
|
+
deleteFile('cache.json');
|
|
1070
|
+
```
|
|
1071
|
+
|
|
1072
|
+
#### <a id="api-sync-getDirectoryElements"></a>`getDirectoryElements`
|
|
1073
|
+
|
|
1074
|
+
*Function*
|
|
1075
|
+
|
|
1076
|
+
Lists a directory's elements grouped by kind: directories, files (filtered by extension), and symbolic links, each group sorted. Entries removed while the directory is read are left out.
|
|
1077
|
+
|
|
1078
|
+
```ts
|
|
1079
|
+
getDirectoryElements(
|
|
1080
|
+
path: string,
|
|
1081
|
+
options?: Partial<IDirectoryElementsOptions>,
|
|
1082
|
+
): IDirectoryPathElements
|
|
1083
|
+
```
|
|
1084
|
+
|
|
1085
|
+
**Parameters**
|
|
1086
|
+
|
|
1087
|
+
- `path` `string`: The directory's path.
|
|
1088
|
+
- `options?` `Partial<IDirectoryElementsOptions>`: The extensions to include and how to sort.
|
|
1089
|
+
|
|
1090
|
+
**Returns** `IDirectoryPathElements`: The grouped elements.
|
|
1091
|
+
|
|
1092
|
+
**Throws**
|
|
1093
|
+
|
|
1094
|
+
- `NOT_A_DIRECTORY`: if the path doesn't exist or is not a directory
|
|
1095
|
+
|
|
1096
|
+
**Example**
|
|
1097
|
+
|
|
1098
|
+
```ts
|
|
1099
|
+
import { getDirectoryElements } from 'jg-fs/sync';
|
|
1100
|
+
|
|
1101
|
+
const { files } = getDirectoryElements('content', { includeExts: ['.md'], sortByKey: 'creation', sortOrder: 'desc' });
|
|
1102
|
+
```
|
|
1103
|
+
|
|
1104
|
+
#### <a id="api-sync-getPathElement"></a>`getPathElement`
|
|
1105
|
+
|
|
1106
|
+
*Function*
|
|
1107
|
+
|
|
1108
|
+
Reads a path's details without following a symbolic link at the path.
|
|
1109
|
+
|
|
1110
|
+
```ts
|
|
1111
|
+
getPathElement(path: string): IPathElement | null
|
|
1112
|
+
```
|
|
1113
|
+
|
|
1114
|
+
**Parameters**
|
|
1115
|
+
|
|
1116
|
+
- `path` `string`: The path.
|
|
1117
|
+
|
|
1118
|
+
**Returns** `IPathElement | null`: The path's details, or `null` when it doesn't exist.
|
|
1119
|
+
|
|
1120
|
+
**Example**
|
|
1121
|
+
|
|
1122
|
+
```ts
|
|
1123
|
+
import { getPathElement } from 'jg-fs/sync';
|
|
1124
|
+
|
|
1125
|
+
const element = getPathElement('logo.png');
|
|
1126
|
+
element?.size; // the size in bytes, or undefined when the path doesn't exist
|
|
1127
|
+
```
|
|
1128
|
+
|
|
1129
|
+
#### <a id="api-sync-isDirectory"></a>`isDirectory`
|
|
1130
|
+
|
|
1131
|
+
*Function*
|
|
1132
|
+
|
|
1133
|
+
Checks whether a path exists and is a directory.
|
|
1134
|
+
|
|
1135
|
+
```ts
|
|
1136
|
+
isDirectory(path: string): boolean
|
|
1137
|
+
```
|
|
1138
|
+
|
|
1139
|
+
**Parameters**
|
|
1140
|
+
|
|
1141
|
+
- `path` `string`: The path.
|
|
1142
|
+
|
|
1143
|
+
**Returns** `boolean`: Whether the path is a directory.
|
|
1144
|
+
|
|
1145
|
+
**Example**
|
|
1146
|
+
|
|
1147
|
+
```ts
|
|
1148
|
+
import { isDirectory } from 'jg-fs/sync';
|
|
1149
|
+
|
|
1150
|
+
isDirectory('dist'); // true
|
|
1151
|
+
```
|
|
1152
|
+
|
|
1153
|
+
#### <a id="api-sync-isFile"></a>`isFile`
|
|
1154
|
+
|
|
1155
|
+
*Function*
|
|
1156
|
+
|
|
1157
|
+
Checks whether a path exists and is a regular file.
|
|
1158
|
+
|
|
1159
|
+
```ts
|
|
1160
|
+
isFile(path: string): boolean
|
|
1161
|
+
```
|
|
1162
|
+
|
|
1163
|
+
**Parameters**
|
|
1164
|
+
|
|
1165
|
+
- `path` `string`: The path.
|
|
1166
|
+
|
|
1167
|
+
**Returns** `boolean`: Whether the path is a file.
|
|
1168
|
+
|
|
1169
|
+
**Example**
|
|
1170
|
+
|
|
1171
|
+
```ts
|
|
1172
|
+
import { isFile } from 'jg-fs/sync';
|
|
1173
|
+
|
|
1174
|
+
isFile('package.json'); // true
|
|
1175
|
+
```
|
|
1176
|
+
|
|
1177
|
+
#### <a id="api-sync-isPathWithin"></a>`isPathWithin`
|
|
1178
|
+
|
|
1179
|
+
*Function*
|
|
1180
|
+
|
|
1181
|
+
Checks whether a path is a root path or nested inside it. The check is lexical: both paths are resolved without touching the filesystem, and symbolic links aren't followed. Sibling paths that share a prefix, such as `/data/app` and `/data/application`, aren't nested, and neither is a path on another drive on Windows.
|
|
1182
|
+
|
|
1183
|
+
```ts
|
|
1184
|
+
isPathWithin(rootPath: string, targetPath: string): boolean
|
|
1185
|
+
```
|
|
1186
|
+
|
|
1187
|
+
**Parameters**
|
|
1188
|
+
|
|
1189
|
+
- `rootPath` `string`: The root path.
|
|
1190
|
+
- `targetPath` `string`: The path to check.
|
|
1191
|
+
|
|
1192
|
+
**Returns** `boolean`: Whether the target is the root or inside it.
|
|
1193
|
+
|
|
1194
|
+
**Example**
|
|
1195
|
+
|
|
1196
|
+
```ts
|
|
1197
|
+
import { isPathWithin } from 'jg-fs';
|
|
1198
|
+
|
|
1199
|
+
isPathWithin('/data/app', '/data/app/logs/today.log'); // true
|
|
1200
|
+
isPathWithin('/data/app', '/data/app/../secrets'); // false
|
|
1201
|
+
isPathWithin('/data/app', '/data/application'); // false
|
|
1202
|
+
```
|
|
1203
|
+
|
|
1204
|
+
#### <a id="api-sync-pathExists"></a>`pathExists`
|
|
1205
|
+
|
|
1206
|
+
*Function*
|
|
1207
|
+
|
|
1208
|
+
Checks whether a path exists, whether it's a file, a directory, or anything else.
|
|
1209
|
+
|
|
1210
|
+
```ts
|
|
1211
|
+
pathExists(path: string): boolean
|
|
1212
|
+
```
|
|
1213
|
+
|
|
1214
|
+
**Parameters**
|
|
1215
|
+
|
|
1216
|
+
- `path` `string`: The path.
|
|
1217
|
+
|
|
1218
|
+
**Returns** `boolean`: Whether the path exists.
|
|
1219
|
+
|
|
1220
|
+
**Example**
|
|
1221
|
+
|
|
1222
|
+
```ts
|
|
1223
|
+
import { pathExists } from 'jg-fs/sync';
|
|
1224
|
+
|
|
1225
|
+
pathExists('config.json'); // true when the file exists
|
|
1226
|
+
```
|
|
1227
|
+
|
|
1228
|
+
#### <a id="api-sync-readBoundedFile"></a>`readBoundedFile`
|
|
1229
|
+
|
|
1230
|
+
*Function*
|
|
1231
|
+
|
|
1232
|
+
Reads a regular file of at most `maxBytes` bytes. It never follows a symbolic link in the path's last component, though links in parent directories are followed, so callers that need containment combine it with `isPathWithin`. It reads at most `maxBytes + 1` bytes, even when the file grows while it's read.
|
|
1233
|
+
|
|
1234
|
+
```ts
|
|
1235
|
+
readBoundedFile(path: string, maxBytes: number): Buffer
|
|
1236
|
+
```
|
|
1237
|
+
|
|
1238
|
+
**Parameters**
|
|
1239
|
+
|
|
1240
|
+
- `path` `string`: The file's path.
|
|
1241
|
+
- `maxBytes` `number`: The largest size accepted, in bytes.
|
|
1242
|
+
|
|
1243
|
+
**Returns** `Buffer`: The content.
|
|
1244
|
+
|
|
1245
|
+
**Throws**
|
|
1246
|
+
|
|
1247
|
+
- `NOT_A_FILE`: if the path doesn't exist, its final component is a symbolic link, or it isn't a regular file
|
|
1248
|
+
- `FILE_TOO_LARGE`: if the file holds more than maxBytes bytes
|
|
1249
|
+
|
|
1250
|
+
**Example**
|
|
1251
|
+
|
|
1252
|
+
```ts
|
|
1253
|
+
import { join } from 'node:path';
|
|
1254
|
+
import { readBoundedFile } from 'jg-fs/sync';
|
|
1255
|
+
|
|
1256
|
+
const upload = readBoundedFile(join('uploads', 'avatar.png'), 5 * 1024 * 1024); // at most 5 MB
|
|
1257
|
+
```
|
|
1258
|
+
|
|
1259
|
+
#### <a id="api-sync-readBufferFile"></a>`readBufferFile`
|
|
1260
|
+
|
|
1261
|
+
*Function*
|
|
1262
|
+
|
|
1263
|
+
Reads a binary file. An empty file reads as an empty Buffer.
|
|
1264
|
+
|
|
1265
|
+
```ts
|
|
1266
|
+
readBufferFile(path: string): Buffer
|
|
1267
|
+
```
|
|
1268
|
+
|
|
1269
|
+
**Parameters**
|
|
1270
|
+
|
|
1271
|
+
- `path` `string`: The file's path.
|
|
1272
|
+
|
|
1273
|
+
**Returns** `Buffer`: The content.
|
|
1274
|
+
|
|
1275
|
+
**Throws**
|
|
1276
|
+
|
|
1277
|
+
- `NOT_A_FILE`: if the path doesn't exist or is not a file
|
|
1278
|
+
|
|
1279
|
+
**Example**
|
|
1280
|
+
|
|
1281
|
+
```ts
|
|
1282
|
+
import { readBufferFile } from 'jg-fs/sync';
|
|
1283
|
+
|
|
1284
|
+
const image = readBufferFile('avatar.png');
|
|
1285
|
+
```
|
|
1286
|
+
|
|
1287
|
+
#### <a id="api-sync-readDirectory"></a>`readDirectory`
|
|
1288
|
+
|
|
1289
|
+
*Function*
|
|
1290
|
+
|
|
1291
|
+
Lists a directory's contents as paths joined to the directory's path.
|
|
1292
|
+
|
|
1293
|
+
```ts
|
|
1294
|
+
readDirectory(path: string, recursive?: boolean): string[]
|
|
1295
|
+
```
|
|
1296
|
+
|
|
1297
|
+
**Parameters**
|
|
1298
|
+
|
|
1299
|
+
- `path` `string`: The directory's path.
|
|
1300
|
+
- `recursive?` `boolean`: Whether to include the contents of subdirectories. Defaults to `false`.
|
|
1301
|
+
|
|
1302
|
+
**Returns** `string[]`: The content paths.
|
|
1303
|
+
|
|
1304
|
+
**Throws**
|
|
1305
|
+
|
|
1306
|
+
- `NOT_A_DIRECTORY`: if the path doesn't exist or is not a directory
|
|
1307
|
+
|
|
1308
|
+
**Example**
|
|
1309
|
+
|
|
1310
|
+
```ts
|
|
1311
|
+
import { readDirectory } from 'jg-fs/sync';
|
|
1312
|
+
|
|
1313
|
+
readDirectory('dist'); // ['dist/index.js', 'dist/assets']
|
|
1314
|
+
readDirectory('dist', true); // includes the contents of dist/assets
|
|
1315
|
+
```
|
|
1316
|
+
|
|
1317
|
+
#### <a id="api-sync-readFile"></a>`readFile`
|
|
1318
|
+
|
|
1319
|
+
*Function*
|
|
1320
|
+
|
|
1321
|
+
Reads a file as a string when an encoding is given, or as a Buffer otherwise.
|
|
1322
|
+
|
|
1323
|
+
```ts
|
|
1324
|
+
readFile(path: string, options: IReadStringFileOptions): string
|
|
1325
|
+
```
|
|
1326
|
+
|
|
1327
|
+
**Parameters**
|
|
1328
|
+
|
|
1329
|
+
- `path` `string`: The file's path.
|
|
1330
|
+
- `options` `IReadStringFileOptions`: Node.js's readFile options, such as the encoding.
|
|
1331
|
+
|
|
1332
|
+
**Returns** `string`: The content.
|
|
1333
|
+
|
|
1334
|
+
**Throws**
|
|
1335
|
+
|
|
1336
|
+
- `NOT_A_FILE`: if the path doesn't exist or is not a file
|
|
1337
|
+
|
|
1338
|
+
```ts
|
|
1339
|
+
readFile(path: string, options?: IReadBufferFileOptions): Buffer
|
|
1340
|
+
```
|
|
1341
|
+
|
|
1342
|
+
**Parameters**
|
|
1343
|
+
|
|
1344
|
+
- `path` `string`: The file's path.
|
|
1345
|
+
- `options?` `IReadBufferFileOptions`: Node.js's readFile options, such as the encoding.
|
|
1346
|
+
|
|
1347
|
+
**Returns** `Buffer`: The content.
|
|
1348
|
+
|
|
1349
|
+
**Throws**
|
|
1350
|
+
|
|
1351
|
+
- `NOT_A_FILE`: if the path doesn't exist or is not a file
|
|
1352
|
+
|
|
1353
|
+
```ts
|
|
1354
|
+
readFile(
|
|
1355
|
+
path: string,
|
|
1356
|
+
options?: IReadFileOptions,
|
|
1357
|
+
): string | Buffer<ArrayBufferLike>
|
|
1358
|
+
```
|
|
1359
|
+
|
|
1360
|
+
**Parameters**
|
|
1361
|
+
|
|
1362
|
+
- `path` `string`: The file's path.
|
|
1363
|
+
- `options?` `IReadFileOptions`: Node.js's readFile options, such as the encoding.
|
|
1364
|
+
|
|
1365
|
+
**Returns** `string | Buffer<ArrayBufferLike>`: The content.
|
|
1366
|
+
|
|
1367
|
+
**Throws**
|
|
1368
|
+
|
|
1369
|
+
- `NOT_A_FILE`: if the path doesn't exist or is not a file
|
|
1370
|
+
|
|
1371
|
+
**Example**
|
|
1372
|
+
|
|
1373
|
+
```ts
|
|
1374
|
+
import { readFile } from 'jg-fs/sync';
|
|
1375
|
+
|
|
1376
|
+
readFile('notes.md', 'utf-8'); // a string
|
|
1377
|
+
readFile('avatar.png'); // a Buffer
|
|
1378
|
+
```
|
|
1379
|
+
|
|
1380
|
+
#### <a id="api-sync-readJsonFile"></a>`readJsonFile`
|
|
1381
|
+
|
|
1382
|
+
*Function*
|
|
1383
|
+
|
|
1384
|
+
Reads and parses a JSON file, and validates it with the schema when there is one. Without a schema, the value is `unknown`, or the type you pass.
|
|
1385
|
+
|
|
1386
|
+
```ts
|
|
1387
|
+
readJsonFile<T = unknown>(path: string, options?: IReadJsonFileOptions<T>): T
|
|
1388
|
+
```
|
|
1389
|
+
|
|
1390
|
+
**Parameters**
|
|
1391
|
+
|
|
1392
|
+
- `path` `string`: The file's path.
|
|
1393
|
+
- `options?` `IReadJsonFileOptions<T>`: The schema, such as a Zod schema, whose errors propagate unchanged. Defaults to `{}`.
|
|
1394
|
+
|
|
1395
|
+
**Returns** `T`: The parsed value.
|
|
1396
|
+
|
|
1397
|
+
**Throws**
|
|
1398
|
+
|
|
1399
|
+
- `NOT_A_FILE`: if the path doesn't exist or is not a file
|
|
1400
|
+
- `FILE_CONTENT_IS_EMPTY_OR_INVALID`: if the file's JSON content cannot be parsed
|
|
1401
|
+
|
|
1402
|
+
**Example 1**
|
|
1403
|
+
|
|
1404
|
+
```ts
|
|
1405
|
+
import { readJsonFile } from 'jg-fs/sync';
|
|
1406
|
+
|
|
1407
|
+
const config = readJsonFile('config.json', { schema: Config }); // Config's type
|
|
1408
|
+
```
|
|
1409
|
+
|
|
1410
|
+
**Example 2**
|
|
1411
|
+
|
|
1412
|
+
```ts
|
|
1413
|
+
import { readJsonFile } from 'jg-fs/sync';
|
|
1414
|
+
|
|
1415
|
+
const value = readJsonFile('data.json'); // unknown
|
|
1416
|
+
```
|
|
1417
|
+
|
|
1418
|
+
#### <a id="api-sync-readTextFile"></a>`readTextFile`
|
|
1419
|
+
|
|
1420
|
+
*Function*
|
|
1421
|
+
|
|
1422
|
+
Reads a UTF-8 text file. An empty file reads as an empty string.
|
|
1423
|
+
|
|
1424
|
+
```ts
|
|
1425
|
+
readTextFile(path: string): string
|
|
1426
|
+
```
|
|
1427
|
+
|
|
1428
|
+
**Parameters**
|
|
1429
|
+
|
|
1430
|
+
- `path` `string`: The file's path.
|
|
1431
|
+
|
|
1432
|
+
**Returns** `string`: The text.
|
|
1433
|
+
|
|
1434
|
+
**Throws**
|
|
1435
|
+
|
|
1436
|
+
- `NOT_A_FILE`: if the path doesn't exist or is not a file
|
|
1437
|
+
|
|
1438
|
+
**Example**
|
|
1439
|
+
|
|
1440
|
+
```ts
|
|
1441
|
+
import { readTextFile } from 'jg-fs/sync';
|
|
1442
|
+
|
|
1443
|
+
const markdown = readTextFile('README.md');
|
|
1444
|
+
```
|
|
1445
|
+
|
|
1446
|
+
#### <a id="api-sync-writeBufferFile"></a>`writeBufferFile`
|
|
1447
|
+
|
|
1448
|
+
*Function*
|
|
1449
|
+
|
|
1450
|
+
Writes a binary file. An empty Buffer writes an empty file.
|
|
1451
|
+
|
|
1452
|
+
```ts
|
|
1453
|
+
writeBufferFile(path: string, data: Buffer): void
|
|
1454
|
+
```
|
|
1455
|
+
|
|
1456
|
+
**Parameters**
|
|
1457
|
+
|
|
1458
|
+
- `path` `string`: The file's path.
|
|
1459
|
+
- `data` `Buffer`: The content.
|
|
1460
|
+
|
|
1461
|
+
**Throws**
|
|
1462
|
+
|
|
1463
|
+
- `FILE_CONTENT_IS_EMPTY_OR_INVALID`: if the data isn't a Buffer
|
|
1464
|
+
|
|
1465
|
+
**Example**
|
|
1466
|
+
|
|
1467
|
+
```ts
|
|
1468
|
+
import { writeBufferFile } from 'jg-fs/sync';
|
|
1469
|
+
|
|
1470
|
+
const imageBuffer = Buffer.from('iVBORw0KGgo=', 'base64');
|
|
1471
|
+
writeBufferFile('avatar.png', imageBuffer);
|
|
1472
|
+
```
|
|
1473
|
+
|
|
1474
|
+
#### <a id="api-sync-writeFile"></a>`writeFile`
|
|
1475
|
+
|
|
1476
|
+
*Function*
|
|
1477
|
+
|
|
1478
|
+
Writes a file, creating its directory first when it doesn't exist.
|
|
1479
|
+
|
|
1480
|
+
```ts
|
|
1481
|
+
writeFile(
|
|
1482
|
+
path: string,
|
|
1483
|
+
data: string | ArrayBufferView<ArrayBufferLike>,
|
|
1484
|
+
options?: WriteFileOptions,
|
|
1485
|
+
): void
|
|
1486
|
+
```
|
|
1487
|
+
|
|
1488
|
+
**Parameters**
|
|
1489
|
+
|
|
1490
|
+
- `path` `string`: The file's path.
|
|
1491
|
+
- `data` `string | ArrayBufferView<ArrayBufferLike>`: The content.
|
|
1492
|
+
- `options?` `WriteFileOptions`: Node.js's writeFile options, such as the encoding or mode.
|
|
1493
|
+
|
|
1494
|
+
**Example**
|
|
1495
|
+
|
|
1496
|
+
```ts
|
|
1497
|
+
import { writeFile } from 'jg-fs/sync';
|
|
1498
|
+
|
|
1499
|
+
const csv = 'id,name\n1,Ada\n';
|
|
1500
|
+
writeFile('out/report.csv', csv, { encoding: 'utf-8' });
|
|
1501
|
+
```
|
|
1502
|
+
|
|
1503
|
+
#### <a id="api-sync-writeFileAtomic"></a>`writeFileAtomic`
|
|
1504
|
+
|
|
1505
|
+
*Function*
|
|
1506
|
+
|
|
1507
|
+
Writes a file atomically: readers see either the previous content or the complete new content, never a partial write. The data goes to a temporary file in the same directory, which is flushed to disk and renamed over the path; on POSIX, the directory is flushed too. An explicit mode wins; without one, a replaced file keeps its permission bits and a new file gets the platform default. The temporary file is never more widely readable than the final mode. When writing fails before the rename, the temporary file is removed and the destination is untouched.
|
|
1508
|
+
|
|
1509
|
+
```ts
|
|
1510
|
+
writeFileAtomic(
|
|
1511
|
+
path: string,
|
|
1512
|
+
data: string | ArrayBufferView<ArrayBufferLike>,
|
|
1513
|
+
mode?: number,
|
|
1514
|
+
): void
|
|
1515
|
+
```
|
|
1516
|
+
|
|
1517
|
+
**Parameters**
|
|
1518
|
+
|
|
1519
|
+
- `path` `string`: The file's path.
|
|
1520
|
+
- `data` `string | ArrayBufferView<ArrayBufferLike>`: The content.
|
|
1521
|
+
- `mode?` `number`: The permission bits of the written file, such as `0o600`.
|
|
1522
|
+
|
|
1523
|
+
**Example**
|
|
1524
|
+
|
|
1525
|
+
```ts
|
|
1526
|
+
import { writeFileAtomic } from 'jg-fs/sync';
|
|
1527
|
+
|
|
1528
|
+
const state = { step: 2 };
|
|
1529
|
+
writeFileAtomic('state.json', JSON.stringify(state)); // readers never see a partial file
|
|
1530
|
+
writeFileAtomic('secrets.env', 'TOKEN=abc\n', 0o600); // only the owner can read it
|
|
1531
|
+
```
|
|
1532
|
+
|
|
1533
|
+
#### <a id="api-sync-writeJsonFile"></a>`writeJsonFile`
|
|
1534
|
+
|
|
1535
|
+
*Function*
|
|
1536
|
+
|
|
1537
|
+
Writes a JSON file. A string is written as given; anything else is stringified.
|
|
1538
|
+
|
|
1539
|
+
```ts
|
|
1540
|
+
writeJsonFile<T = Record<string, unknown>>(
|
|
1541
|
+
path: string,
|
|
1542
|
+
data: string | T,
|
|
1543
|
+
space?: number,
|
|
1544
|
+
): void
|
|
1545
|
+
```
|
|
1546
|
+
|
|
1547
|
+
**Parameters**
|
|
1548
|
+
|
|
1549
|
+
- `path` `string`: The file's path.
|
|
1550
|
+
- `data` `string | T`: The value, or its JSON text.
|
|
1551
|
+
- `space?` `number`: The indentation for stringified values. Defaults to `2`.
|
|
1552
|
+
|
|
1553
|
+
**Throws**
|
|
1554
|
+
|
|
1555
|
+
- `FILE_CONTENT_IS_EMPTY_OR_INVALID`: if the JSON content cannot be stringified or is empty
|
|
1556
|
+
|
|
1557
|
+
**Example**
|
|
1558
|
+
|
|
1559
|
+
```ts
|
|
1560
|
+
import { writeJsonFile } from 'jg-fs/sync';
|
|
1561
|
+
|
|
1562
|
+
writeJsonFile('config.json', { port: 8080 });
|
|
1563
|
+
```
|
|
1564
|
+
|
|
1565
|
+
#### <a id="api-sync-writeTextFile"></a>`writeTextFile`
|
|
1566
|
+
|
|
1567
|
+
*Function*
|
|
1568
|
+
|
|
1569
|
+
Writes a UTF-8 text file. An empty string writes an empty file.
|
|
1570
|
+
|
|
1571
|
+
```ts
|
|
1572
|
+
writeTextFile(path: string, data: string): void
|
|
1573
|
+
```
|
|
1574
|
+
|
|
1575
|
+
**Parameters**
|
|
1576
|
+
|
|
1577
|
+
- `path` `string`: The file's path.
|
|
1578
|
+
- `data` `string`: The text.
|
|
1579
|
+
|
|
1580
|
+
**Throws**
|
|
1581
|
+
|
|
1582
|
+
- `FILE_CONTENT_IS_EMPTY_OR_INVALID`: if the data isn't a string
|
|
1583
|
+
|
|
1584
|
+
**Example**
|
|
1585
|
+
|
|
1586
|
+
```ts
|
|
1587
|
+
import { writeTextFile } from 'jg-fs/sync';
|
|
1588
|
+
|
|
1589
|
+
writeTextFile('notes/today.md', '# Today');
|
|
1590
|
+
```
|
|
1591
|
+
|
|
1592
|
+
### <a id="api-sync-constants"></a>Constants in `jg-fs/sync`
|
|
1593
|
+
|
|
1594
|
+
#### <a id="api-sync-ERRORS"></a>`ERRORS`
|
|
1595
|
+
|
|
1596
|
+
*Constant*
|
|
1597
|
+
|
|
1598
|
+
the codes of every error the package throws, from both the async and the sync entry
|
|
1599
|
+
|
|
1600
|
+
```ts
|
|
1601
|
+
const ERRORS: { NOT_A_DIRECTORY: "NOT_A_DIRECTORY"; NON_EXISTENT_DIRECTORY: "NON_EXISTENT_DIRECTORY"; DIRECTORY_ALREADY_EXISTS: "DIRECTORY_ALREADY_EXISTS"; NON_EXISTENT_FILE: "NON_EXISTENT_FILE"; NOT_A_FILE: "NOT_A_FILE"; FILE_CONTENT_IS_EMPTY_OR_INVALID: "FILE_CONTENT_IS_EMPTY_OR_INVALID"; FILE_TOO_LARGE: "FILE_TOO_LARGE" }
|
|
1602
|
+
```
|
|
1603
|
+
|
|
1604
|
+
### <a id="api-sync-types"></a>Types in `jg-fs/sync`
|
|
1605
|
+
|
|
1606
|
+
#### <a id="api-sync-IDirectoryElementsKeySort"></a>`IDirectoryElementsKeySort`
|
|
1607
|
+
|
|
1608
|
+
*Type*
|
|
1609
|
+
|
|
1610
|
+
the keys a directory's elements can be sorted by
|
|
1611
|
+
|
|
1612
|
+
```ts
|
|
1613
|
+
type IDirectoryElementsKeySort = 'baseName' | 'size' | 'creation';
|
|
1614
|
+
```
|
|
1615
|
+
|
|
1616
|
+
#### <a id="api-sync-IDirectoryElementsOptions"></a>`IDirectoryElementsOptions`
|
|
1617
|
+
|
|
1618
|
+
*Type*
|
|
1619
|
+
|
|
1620
|
+
how getDirectoryElements filters and sorts a directory's elements
|
|
1621
|
+
|
|
1622
|
+
```ts
|
|
1623
|
+
type IDirectoryElementsOptions = {
|
|
1624
|
+
sortByKey: IDirectoryElementsKeySort;
|
|
1625
|
+
sortOrder: ISortDirection;
|
|
1626
|
+
includeExts: string[];
|
|
1627
|
+
};
|
|
1628
|
+
```
|
|
1629
|
+
|
|
1630
|
+
**Members**
|
|
1631
|
+
|
|
1632
|
+
- `sortByKey: IDirectoryElementsKeySort` (property): the key the elements are sorted by. Defaults to 'baseName'
|
|
1633
|
+
- `sortOrder: ISortDirection` (property): the sort direction. Defaults to 'asc'
|
|
1634
|
+
- `includeExts: string[]` (property): the extensions of the files to include, such as ['.json'], matched case-insensitively. Defaults to all
|
|
1635
|
+
|
|
1636
|
+
#### <a id="api-sync-IDirectoryPathElements"></a>`IDirectoryPathElements`
|
|
1637
|
+
|
|
1638
|
+
*Type*
|
|
1639
|
+
|
|
1640
|
+
a directory's elements, grouped by kind
|
|
1641
|
+
|
|
1642
|
+
```ts
|
|
1643
|
+
type IDirectoryPathElements = {
|
|
1644
|
+
directories: IPathElement[];
|
|
1645
|
+
files: IPathElement[];
|
|
1646
|
+
symbolicLinks: IPathElement[];
|
|
1647
|
+
};
|
|
1648
|
+
```
|
|
1649
|
+
|
|
1650
|
+
**Members**
|
|
1651
|
+
|
|
1652
|
+
- `directories: IPathElement[]` (property)
|
|
1653
|
+
- `files: IPathElement[]` (property)
|
|
1654
|
+
- `symbolicLinks: IPathElement[]` (property)
|
|
1655
|
+
|
|
1656
|
+
#### <a id="api-sync-IPathElement"></a>`IPathElement`
|
|
1657
|
+
|
|
1658
|
+
*Type*
|
|
1659
|
+
|
|
1660
|
+
the details of a path, read with lstat, so a symbolic link is described rather than followed
|
|
1661
|
+
|
|
1662
|
+
```ts
|
|
1663
|
+
type IPathElement = {
|
|
1664
|
+
path: string;
|
|
1665
|
+
baseName: string;
|
|
1666
|
+
extName: string;
|
|
1667
|
+
isFile: boolean;
|
|
1668
|
+
isDirectory: boolean;
|
|
1669
|
+
isSymbolicLink: boolean;
|
|
1670
|
+
size: number;
|
|
1671
|
+
creation: number;
|
|
1672
|
+
};
|
|
1673
|
+
```
|
|
1674
|
+
|
|
1675
|
+
**Members**
|
|
1676
|
+
|
|
1677
|
+
- `path: string` (property): the path, as given
|
|
1678
|
+
- `baseName: string` (property): the last segment of the path
|
|
1679
|
+
- `extName: string` (property): the extension, such as '.json', or an empty string when there is none
|
|
1680
|
+
- `isFile: boolean` (property): whether it's a regular file
|
|
1681
|
+
- `isDirectory: boolean` (property): whether it's a directory
|
|
1682
|
+
- `isSymbolicLink: boolean` (property): whether it's a symbolic link, in which case isFile and isDirectory are false
|
|
1683
|
+
- `size: number` (property): the size in bytes
|
|
1684
|
+
- `creation: number` (property): when it was created, in milliseconds since the epoch
|
|
1685
|
+
|
|
1686
|
+
#### <a id="api-sync-IReadJsonFileOptions"></a>`IReadJsonFileOptions`
|
|
1687
|
+
|
|
1688
|
+
*Type*
|
|
1689
|
+
|
|
1690
|
+
what readJsonFile accepts
|
|
1691
|
+
|
|
1692
|
+
```ts
|
|
1693
|
+
type IReadJsonFileOptions<T> = {
|
|
1694
|
+
schema?: ISchema<T>;
|
|
1695
|
+
};
|
|
1696
|
+
```
|
|
1697
|
+
|
|
1698
|
+
**Members**
|
|
1699
|
+
|
|
1700
|
+
- `schema: ISchema<T>` (property): validates the parsed content, such as a Zod schema. Its errors propagate unchanged
|
|
1701
|
+
|
|
1702
|
+
#### <a id="api-sync-ISchema"></a>`ISchema`
|
|
1703
|
+
|
|
1704
|
+
*Type*
|
|
1705
|
+
|
|
1706
|
+
validates parsed data and returns it typed, which a Zod schema does
|
|
1707
|
+
|
|
1708
|
+
```ts
|
|
1709
|
+
type ISchema<T> = {
|
|
1710
|
+
parse(value: unknown): T;
|
|
1711
|
+
};
|
|
1712
|
+
```
|
|
1713
|
+
|
|
1714
|
+
**Members**
|
|
1715
|
+
|
|
1716
|
+
- `parse(value: unknown): T` (method)
|