@ix-xs/node-comfort 1.2.0 → 2.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.
Files changed (78) hide show
  1. package/CHANGELOG.md +340 -0
  2. package/README.md +137 -548
  3. package/index.js +80 -35
  4. package/package.json +161 -33
  5. package/src/Arr.js +1050 -418
  6. package/src/Async.js +817 -0
  7. package/src/Cache.js +433 -0
  8. package/src/Checker.js +1202 -539
  9. package/src/Cli.js +1293 -0
  10. package/src/Color.js +556 -0
  11. package/src/Crypto.js +1082 -0
  12. package/src/Emitter.js +356 -0
  13. package/src/Env.js +689 -0
  14. package/src/FS.js +1626 -894
  15. package/src/Func.js +823 -356
  16. package/src/Http.js +700 -0
  17. package/src/Id.js +568 -200
  18. package/src/Logger.js +963 -378
  19. package/src/Num.js +965 -360
  20. package/src/Obj.js +1077 -379
  21. package/src/SQLite.js +1629 -1005
  22. package/src/Schema.js +2101 -0
  23. package/src/Str.js +1209 -432
  24. package/src/Sys.js +654 -0
  25. package/src/Time.js +1533 -440
  26. package/src/Utils.js +342 -325
  27. package/src/errors.js +335 -0
  28. package/src/internal/shared.js +415 -0
  29. package/types/index.d.ts +735 -526
  30. package/types/src/Arr.d.ts +533 -145
  31. package/types/src/Arr.d.ts.map +1 -1
  32. package/types/src/Async.d.ts +372 -0
  33. package/types/src/Async.d.ts.map +1 -0
  34. package/types/src/Cache.d.ts +221 -0
  35. package/types/src/Cache.d.ts.map +1 -0
  36. package/types/src/Checker.d.ts +651 -232
  37. package/types/src/Checker.d.ts.map +1 -1
  38. package/types/src/Cli.d.ts +664 -0
  39. package/types/src/Cli.d.ts.map +1 -0
  40. package/types/src/Color.d.ts +300 -0
  41. package/types/src/Color.d.ts.map +1 -0
  42. package/types/src/Crypto.d.ts +620 -0
  43. package/types/src/Crypto.d.ts.map +1 -0
  44. package/types/src/Emitter.d.ts +189 -0
  45. package/types/src/Emitter.d.ts.map +1 -0
  46. package/types/src/Env.d.ts +412 -0
  47. package/types/src/Env.d.ts.map +1 -0
  48. package/types/src/FS.d.ts +717 -238
  49. package/types/src/FS.d.ts.map +1 -1
  50. package/types/src/Func.d.ts +508 -135
  51. package/types/src/Func.d.ts.map +1 -1
  52. package/types/src/Http.d.ts +444 -0
  53. package/types/src/Http.d.ts.map +1 -0
  54. package/types/src/Id.d.ts +199 -66
  55. package/types/src/Id.d.ts.map +1 -1
  56. package/types/src/Logger.d.ts +414 -46
  57. package/types/src/Logger.d.ts.map +1 -1
  58. package/types/src/Num.d.ts +514 -137
  59. package/types/src/Num.d.ts.map +1 -1
  60. package/types/src/Obj.d.ts +453 -104
  61. package/types/src/Obj.d.ts.map +1 -1
  62. package/types/src/SQLite.d.ts +754 -308
  63. package/types/src/SQLite.d.ts.map +1 -1
  64. package/types/src/Schema.d.ts +1189 -0
  65. package/types/src/Schema.d.ts.map +1 -0
  66. package/types/src/Str.d.ts +617 -166
  67. package/types/src/Str.d.ts.map +1 -1
  68. package/types/src/Sys.d.ts +314 -0
  69. package/types/src/Sys.d.ts.map +1 -0
  70. package/types/src/Time.d.ts +759 -204
  71. package/types/src/Time.d.ts.map +1 -1
  72. package/types/src/Utils.d.ts +158 -102
  73. package/types/src/Utils.d.ts.map +1 -1
  74. package/types/src/errors.d.ts +316 -0
  75. package/types/src/errors.d.ts.map +1 -0
  76. package/types/src/internal/shared.d.ts +123 -0
  77. package/types/src/internal/shared.d.ts.map +1 -0
  78. package/types/index.d.ts.map +0 -1
package/types/src/FS.d.ts CHANGED
@@ -1,303 +1,782 @@
1
1
  /**
2
- * Reads an environment variable from process.env.
3
- * @param {string} value - The environment variable name.
4
- * @param {string} [envFilePath] - Reserved for future use.
5
- * @returns {string|undefined} The environment value, or undefined if not set.
2
+ * Options for `copyFoldersIn()` and `moveFoldersIn()`.
6
3
  */
7
- export function getEnv(value: string, envFilePath?: string): string | undefined;
4
+ export type CopyFoldersOptions = {
5
+ /**
6
+ * Destination folder.
7
+ */
8
+ dest: string;
9
+ /**
10
+ * Source folder. Defaults to the working directory.
11
+ */
12
+ path?: string | undefined;
13
+ /**
14
+ * Include nested folders. Defaults to `true`.
15
+ */
16
+ recursive?: boolean | undefined;
17
+ /**
18
+ * Copy the files in each folder too.
19
+ */
20
+ withFiles?: boolean | undefined;
21
+ /**
22
+ * Delete an existing destination folder first.
23
+ */
24
+ force?: boolean | undefined;
25
+ /**
26
+ * Keep a folder when it returns `true`. Gets absolute paths.
27
+ */
28
+ filter?: ((folder: string) => boolean) | undefined;
29
+ };
8
30
  /**
9
- * Resolves a path even when it does not already exist.
10
- * @param {string} [path=process.cwd()] - The path to resolve.
11
- * @returns {string} The resolved path.
31
+ * Options for `copyFolder()` and `moveFolder()`.
12
32
  */
13
- export function createPath(path?: string): string;
33
+ export type CopyFolderOptions = {
34
+ /**
35
+ * Destination folder.
36
+ */
37
+ dest: string;
38
+ /**
39
+ * Source folder. Defaults to the working directory.
40
+ */
41
+ path?: string | undefined;
42
+ /**
43
+ * Copy nested folders too.
44
+ */
45
+ recursive?: boolean | undefined;
46
+ /**
47
+ * Copy files too. `copy()` does all of this in one call.
48
+ */
49
+ withFiles?: boolean | undefined;
50
+ /**
51
+ * Delete an existing destination first.
52
+ */
53
+ force?: boolean | undefined;
54
+ };
14
55
  /**
15
- * Returns folders found inside a path.
16
- * @param {string} [path=process.cwd()] - The base path to inspect.
17
- * @param {boolean} [recursive=true] - Whether to scan recursively.
18
- * @returns {string[]|undefined} Matching folders, or undefined if the path cannot be resolved.
56
+ * Options for `copyFilesIn()` and `moveFilesIn()`.
19
57
  */
20
- export function getFoldersIn(path?: string, recursive?: boolean): string[] | undefined;
58
+ export type CopyFilesOptions = {
59
+ /**
60
+ * Destination folder.
61
+ */
62
+ dest: string;
63
+ /**
64
+ * Source folder. Defaults to the working directory.
65
+ */
66
+ path?: string | undefined;
67
+ /**
68
+ * Include files from nested folders, keeping the tree. Defaults to `true`.
69
+ */
70
+ recursive?: boolean | undefined;
71
+ /**
72
+ * Delete existing destination files first.
73
+ */
74
+ force?: boolean | undefined;
75
+ /**
76
+ * Keep a file when it returns `true`. Gets absolute paths.
77
+ */
78
+ filter?: ((file: string) => boolean) | undefined;
79
+ };
21
80
  /**
22
- * Returns the resolved folder path.
23
- * @param {string} [path=process.cwd()] - The folder path to resolve.
24
- * @returns {string|undefined} The resolved folder path, or undefined if not found.
81
+ * Options for `copyFile()` and `moveFile()`.
25
82
  */
26
- export function getFolder(path?: string): string | undefined;
83
+ export type CopyFileOptions = {
84
+ /**
85
+ * Source file.
86
+ */
87
+ path: string;
88
+ /**
89
+ * Destination file, or a folder if it ends with `/`.
90
+ */
91
+ dest: string;
92
+ /**
93
+ * Delete the destination first.
94
+ */
95
+ force?: boolean | undefined;
96
+ };
97
+ /**
98
+ * Options for `copy()`.
99
+ */
100
+ export type CopyOptions = {
101
+ /**
102
+ * Replace existing files. Defaults to `true`.
103
+ */
104
+ overwrite?: boolean | undefined;
105
+ /**
106
+ * Return `false` to skip a file or folder.
107
+ */
108
+ filter?: ((source: string, destination: string) => boolean) | undefined;
109
+ /**
110
+ * Keep modification times.
111
+ */
112
+ preserveTimestamps?: boolean | undefined;
113
+ };
114
+ /**
115
+ * Options for `writeFile()`.
116
+ */
117
+ export type WriteFileOptions = {
118
+ /**
119
+ * Write to a temporary file and rename it, so nobody reads a half-written file and a crash can't corrupt it. Defaults to `true`.
120
+ */
121
+ atomic?: boolean | undefined;
122
+ /**
123
+ * Defaults to `"utf8"`.
124
+ */
125
+ encoding?: BufferEncoding | undefined;
126
+ /**
127
+ * Permissions, like `0o600` for secrets. A file that already exists keeps the ones it has.
128
+ */
129
+ mode?: number | undefined;
130
+ /**
131
+ * Wait until the data is on the disk before returning. Slower, for files that must survive a power cut.
132
+ */
133
+ fsync?: boolean | undefined;
134
+ /**
135
+ * Indentation when writing an object as JSON. Defaults to `2`.
136
+ */
137
+ spaces?: number | undefined;
138
+ };
139
+ /**
140
+ * Options for `writeJSON()`.
141
+ */
142
+ export type WriteJSONOptions = {
143
+ /**
144
+ * Defaults to `2`.
145
+ */
146
+ spaces?: number | undefined;
147
+ /**
148
+ * Defaults to `true`.
149
+ */
150
+ atomic?: boolean | undefined;
151
+ /**
152
+ * Passed to `JSON.stringify`.
153
+ */
154
+ replacer?: ((key: string, value: unknown) => unknown) | undefined;
155
+ /**
156
+ * Permissions, like `0o600` for secrets. A file that already exists keeps the ones it has.
157
+ */
158
+ mode?: number | undefined;
159
+ /**
160
+ * Wait until the data is on the disk before returning.
161
+ */
162
+ fsync?: boolean | undefined;
163
+ };
164
+ /**
165
+ * Options for `readJSON()`.
166
+ */
167
+ export type ReadJSONOptions = {
168
+ /**
169
+ * Allow comments and trailing commas, like in `tsconfig.json`.
170
+ */
171
+ comments?: boolean | undefined;
172
+ /**
173
+ * Passed to `JSON.parse`.
174
+ */
175
+ reviver?: ((key: string, value: any) => any) | undefined;
176
+ };
177
+ /**
178
+ * Options for `getFilesIn()` and `getFoldersIn()`.
179
+ */
180
+ export type ListOptions = {
181
+ /**
182
+ * Go into nested folders. Defaults to `true`.
183
+ */
184
+ recursive?: boolean | undefined;
185
+ /**
186
+ * Include names starting with a dot. Defaults to `true`.
187
+ */
188
+ hidden?: boolean | undefined;
189
+ /**
190
+ * Folder names to skip. Defaults to `["node_modules"]`.
191
+ */
192
+ ignore?: string[] | undefined;
193
+ };
194
+ /**
195
+ * Options for `glob()`.
196
+ */
197
+ export type GlobOptions = {
198
+ /**
199
+ * Where the pattern starts. Defaults to the working directory.
200
+ */
201
+ cwd?: string | undefined;
202
+ /**
203
+ * Return absolute paths.
204
+ */
205
+ absolute?: boolean | undefined;
206
+ /**
207
+ * Let `*` and `**` match names starting with a dot.
208
+ */
209
+ dot?: boolean | undefined;
210
+ /**
211
+ * Patterns to leave out. Defaults to `node_modules` and `.git`.
212
+ */
213
+ ignore?: string[] | undefined;
214
+ /**
215
+ * Defaults to `"files"`.
216
+ */
217
+ type?: "files" | "folders" | "all" | undefined;
218
+ };
219
+ /**
220
+ * Options for `find()`.
221
+ */
222
+ export type FindOptions = {
223
+ /**
224
+ * Where to start. Defaults to the working directory.
225
+ */
226
+ cwd?: string | undefined;
227
+ /**
228
+ * Defaults to `"file"`.
229
+ */
230
+ type?: "file" | "folder" | "any" | undefined;
231
+ /**
232
+ * Folder names to skip. Defaults to `node_modules` and `.git`.
233
+ */
234
+ ignore?: string[] | undefined;
235
+ };
236
+ /**
237
+ * Options for `watch()`.
238
+ */
239
+ export type WatchOptions = {
240
+ /**
241
+ * What to watch. Defaults to the working directory.
242
+ */
243
+ path?: string | undefined;
244
+ /**
245
+ * Watch nested folders too.
246
+ */
247
+ recursive?: boolean | undefined;
248
+ /**
249
+ * Return `false` to ignore an event.
250
+ */
251
+ filter?: ((event: "rename" | "change", file: string) => boolean) | undefined;
252
+ /**
253
+ * Merge events on the same file within this long, in ms or like `"100ms"`. Editors often save in several steps.
254
+ */
255
+ debounce?: string | number | undefined;
256
+ };
257
+ /**
258
+ * Returned by `watch()`.
259
+ */
260
+ export type Watcher = {
261
+ /**
262
+ * Listens for changes. `"all"` also gets the event name. `"error"` tells you the watch broke, for instance because the folder was deleted.
263
+ */
264
+ on: <E extends "change" | "rename" | "all" | "error">(event: E, callback: E extends "all" ? (event: "change" | "rename", file: string) => void : E extends "error" ? (error: Error) => void : (file: string) => void) => Watcher;
265
+ /**
266
+ * Stops watching.
267
+ */
268
+ stop: () => void;
269
+ /**
270
+ * Ignores events until `resume()`.
271
+ */
272
+ pause: () => Watcher;
273
+ resume: () => Watcher;
274
+ };
27
275
  /**
28
- * Returns files found inside a path.
29
- * @param {string} [path=process.cwd()] - The base path to inspect.
30
- * @param {boolean} [recursive=true] - Whether to scan recursively.
31
- * @returns {string[]|undefined} Matching files, or undefined if the path cannot be resolved.
276
+ * Reads an environment variable. For typed and checked values, see `nc.env`.
277
+ *
278
+ * @example
279
+ * nc.getEnv("REGION", "eu-west-1");
280
+ *
281
+ * @param {string} name
282
+ * @param {string} [fallback]
283
+ * @returns {string | undefined}
32
284
  */
33
- export function getFilesIn(path?: string, recursive?: boolean): string[] | undefined;
285
+ export function getEnv(name: string, fallback?: string): string | undefined;
34
286
  /**
35
- * Returns the resolved file path.
36
- * @param {string} path - The file path to resolve.
37
- * @returns {string|undefined} The resolved file path, or undefined if not found.
287
+ * The absolute version of a path, whether it exists or not.
288
+ *
289
+ * @example
290
+ * nc.createPath("./config/app.json"); // next to the calling file
291
+ * nc.createPath("logs/app.log"); // from the working directory
292
+ *
293
+ * @param {string} [path] Defaults to the working directory.
294
+ * @returns {string}
295
+ */
296
+ export function createPath(path?: string): string;
297
+ /**
298
+ * The absolute path of a folder, or `undefined` if it doesn't exist.
299
+ *
300
+ * @example
301
+ * if (!nc.getFolder("./uploads")) nc.createFolder("./uploads");
302
+ *
303
+ * @param {string} [path] Defaults to the working directory.
304
+ * @returns {string | undefined}
305
+ */
306
+ export function getFolder(path?: string): string | undefined;
307
+ /**
308
+ * The absolute path of a file, or `undefined` if it doesn't exist.
309
+ *
310
+ * @param {string} path
311
+ * @returns {string | undefined}
38
312
  */
39
313
  export function getFile(path: string): string | undefined;
40
314
  /**
41
- * Creates a folder.
42
- * @param {string} path - The folder path to create.
43
- * @param {boolean} [force=false] - Whether to recreate the folder if it already exists.
44
- * @returns {boolean|undefined} True on success, false on failure, undefined if no path was provided.
315
+ * The folders inside a folder, nested ones included by default.
316
+ * `node_modules` is skipped.
317
+ *
318
+ * @example
319
+ * nc.getFoldersIn("./src"); // everything
320
+ * nc.getFoldersIn("./src", false); // direct children only
321
+ *
322
+ * @param {string} [path] Defaults to the working directory.
323
+ * @param {boolean | ListOptions} [recursive=true]
324
+ * @returns {string[] | undefined} Absolute paths, or `undefined` if the folder doesn't exist.
325
+ */
326
+ export function getFoldersIn(path?: string, recursive?: boolean | ListOptions): string[] | undefined;
327
+ /**
328
+ * The files inside a folder, nested ones included by default.
329
+ * `node_modules` is skipped.
330
+ *
331
+ * @example
332
+ * nc.getFilesIn("./src").filter((file) => file.endsWith(".js"));
333
+ *
334
+ * @param {string} [path] Defaults to the working directory.
335
+ * @param {boolean | ListOptions} [recursive=true]
336
+ * @returns {string[] | undefined} Absolute paths, or `undefined` if the folder doesn't exist.
337
+ */
338
+ export function getFilesIn(path?: string, recursive?: boolean | ListOptions): string[] | undefined;
339
+ /**
340
+ * Finds paths matching a glob pattern: `*` (anything but `/`), `**` (any
341
+ * depth), `?`, `[abc]` and `{js,ts}`.
342
+ *
343
+ * A pattern starting from the root of the disk searches there, and its
344
+ * results are absolute.
345
+ *
346
+ * @example
347
+ * nc.glob("src/**\/*.js"); // ["src/index.js", "src/lib/a.js"]
348
+ * nc.glob("**\/*.{png,jpg}", { cwd: "./assets", absolute: true });
349
+ * nc.glob("packages/*", { type: "folders" });
350
+ * nc.glob(`${folder}/**\/*.json`); // absolute pattern, absolute results
351
+ *
352
+ * @param {string | string[]} pattern One or more patterns.
353
+ * @param {GlobOptions} [options]
354
+ * @returns {string[]} Sorted, relative to `cwd` with `/` separators, unless the pattern is absolute or `absolute` is set.
355
+ */
356
+ export function glob(pattern: string | string[], options?: GlobOptions): string[];
357
+ /**
358
+ * Searches a folder tree for the first file or folder with this name,
359
+ * closest first.
360
+ *
361
+ * @example
362
+ * nc.find("config.json");
363
+ * nc.find("fixtures", { type: "folder", cwd: "./test" });
364
+ *
365
+ * @param {string} name
366
+ * @param {FindOptions} [options]
367
+ * @returns {string | undefined} The absolute path.
368
+ */
369
+ export function find(name: string, options?: FindOptions): string | undefined;
370
+ /**
371
+ * Looks for a file or folder in a folder, then in its parent, and so on up
372
+ * to the root. It's how you find the `package.json` or the `.git` a file
373
+ * belongs to.
374
+ *
375
+ * @example
376
+ * nc.findUp("package.json"); // the closest one above the working directory
377
+ * nc.findUp(".git", { type: "folder", cwd: __dirname });
378
+ * nc.findUp(["pnpm-lock.yaml", "yarn.lock", "package-lock.json"]);
379
+ *
380
+ * @param {string | string[]} name One name, or several to try in each folder, in this order.
381
+ * @param {{ cwd?: string, type?: "file" | "folder" | "any", stopAt?: string }} [options] Where to start (the working directory by default), what to look for (`"any"` by default), and a folder not to go above.
382
+ * @returns {string | undefined} The absolute path.
383
+ */
384
+ export function findUp(name: string | string[], options?: {
385
+ cwd?: string;
386
+ type?: "file" | "folder" | "any";
387
+ stopAt?: string;
388
+ }): string | undefined;
389
+ /**
390
+ * Reads a file as text, or as a Buffer with `"buffer"`.
391
+ *
392
+ * @example
393
+ * const text = nc.readFile("./README.md");
394
+ * const bytes = nc.readFile("./logo.png", "buffer");
395
+ *
396
+ * @overload
397
+ * @param {string} path
398
+ * @param {"buffer"} encoding
399
+ * @returns {Buffer | undefined} `undefined` if it can't be read.
400
+ */
401
+ export function readFile(path: string, encoding: "buffer"): Buffer | undefined;
402
+ /**
403
+ * Reads a file as text.
404
+ *
405
+ * @overload
406
+ * @param {string} path
407
+ * @param {BufferEncoding} [encoding="utf8"]
408
+ * @returns {string | undefined} `undefined` if it can't be read.
409
+ */
410
+ export function readFile(path: string, encoding?: BufferEncoding | undefined): string | undefined;
411
+ /**
412
+ * Reads a text file as lines. A final newline doesn't add an empty line.
413
+ *
414
+ * @example
415
+ * for (const url of nc.readLines("./urls.txt") ?? []) await check(url);
416
+ *
417
+ * @param {string} path
418
+ * @returns {string[] | undefined} `undefined` if it can't be read.
419
+ */
420
+ export function readLines(path: string): string[] | undefined;
421
+ /**
422
+ * Reads a JSON file. If it's missing or invalid you get `fallback`, never
423
+ * an error.
424
+ *
425
+ * @example
426
+ * const settings = nc.readJSON("./settings.json", { theme: "light" });
427
+ * const tsconfig = nc.readJSON("./tsconfig.json", {}, { comments: true });
428
+ *
429
+ * @template [T=any]
430
+ * @param {string} path
431
+ * @param {T} [fallback]
432
+ * @param {ReadJSONOptions} [options]
433
+ * @returns {T}
434
+ */
435
+ export function readJSON<T = any>(path: string, fallback?: T, options?: ReadJSONOptions): T;
436
+ /**
437
+ * Writes a file atomically, creating its folders. Objects are written as
438
+ * JSON.
439
+ *
440
+ * @example
441
+ * nc.writeFile("./dist/index.html", html);
442
+ * nc.writeFile("./.secrets/token", token, { mode: 0o600 });
443
+ *
444
+ * @param {string} path
445
+ * @param {string | Buffer | Uint8Array | object} data
446
+ * @param {WriteFileOptions} [options]
447
+ * @returns {boolean} `false` if it failed.
448
+ */
449
+ export function writeFile(path: string, data: string | Buffer | Uint8Array | object, options?: WriteFileOptions): boolean;
450
+ /**
451
+ * Writes a value as JSON, atomically, creating folders.
452
+ *
453
+ * @example
454
+ * nc.writeJSON("./data/users.json", users);
455
+ *
456
+ * @param {string} path
457
+ * @param {unknown} data
458
+ * @param {WriteJSONOptions} [options]
459
+ * @returns {boolean} `false` if it failed, for example on a circular structure.
460
+ */
461
+ export function writeJSON(path: string, data: unknown, options?: WriteJSONOptions): boolean;
462
+ /**
463
+ * Appends to a file, creating it and its folders if needed.
464
+ *
465
+ * @example
466
+ * nc.appendFile("./logs/audit.log", `${new Date().toISOString()} login ${user}\n`);
467
+ *
468
+ * @param {string} path
469
+ * @param {string | Buffer} data
470
+ * @returns {boolean}
471
+ */
472
+ export function appendFile(path: string, data: string | Buffer): boolean;
473
+ /**
474
+ * Creates a file and its folders.
475
+ *
476
+ * @example
477
+ * nc.createFile("./notes.txt", false, "hello"); // only if it doesn't exist
478
+ * nc.createFile("./data.json", true, { ok: true }); // replace it
479
+ *
480
+ * @param {string} path
481
+ * @param {boolean} [force=false] Replace the file if it exists.
482
+ * @param {string | Buffer | object | null} [data] Objects are written as JSON.
483
+ * @returns {boolean | undefined} `false` if it already existed or failed.
484
+ */
485
+ export function createFile(path: string, force?: boolean, data?: string | Buffer | object | null): boolean | undefined;
486
+ /**
487
+ * Creates a folder and its parents.
488
+ *
489
+ * @example
490
+ * nc.createFolder("./uploads");
491
+ * nc.createFolder("./cache", true); // start from an empty folder
492
+ *
493
+ * @param {string} path
494
+ * @param {boolean} [force=false] Delete and recreate it if it exists.
495
+ * @returns {boolean | undefined} `false` if it already existed or failed.
45
496
  */
46
497
  export function createFolder(path: string, force?: boolean): boolean | undefined;
47
498
  /**
48
- * Creates a file.
49
- * @param {string} path - The file path to create.
50
- * @param {boolean} [force=false] - Whether to recreate the file if it already exists.
51
- * @param {string|object|null|undefined} [data] - File content to write.
52
- * @returns {boolean|undefined} True on success, false on failure, undefined if no path was provided.
499
+ * Makes sure a folder exists and returns its absolute path.
500
+ *
501
+ * @example
502
+ * const dir = nc.ensureFolder("./storage/uploads");
503
+ *
504
+ * @param {string} path
505
+ * @returns {string}
506
+ * @throws {Error} If it can't be created.
53
507
  */
54
- export function createFile(path: string, force?: boolean, data?: string | object | null | undefined): boolean | undefined;
508
+ export function ensureFolder(path: string): string;
55
509
  /**
56
- * Deletes folders found inside a path.
57
- * @param {string} [path=process.cwd()] - The base path to inspect.
58
- * @param {(folder: string) => boolean} [filter=() => true] - Filter applied to each folder path.
59
- * @returns {number|undefined} Number of deleted folders, or undefined if the path cannot be resolved.
510
+ * Makes sure a file exists (an empty one if needed) and returns its
511
+ * absolute path. An existing file is left as is.
512
+ *
513
+ * @param {string} path
514
+ * @returns {string}
515
+ * @throws {Error} If it can't be created.
60
516
  */
61
- export function deleteFoldersIn(path?: string, filter?: (folder: string) => boolean): number | undefined;
517
+ export function ensureFile(path: string): string;
62
518
  /**
63
- * Deletes a folder.
64
- * @param {string} path - The folder path to delete.
65
- * @returns {boolean|undefined} True on success, false on failure, undefined if the path is invalid.
519
+ * Updates a file's modification time, creating the file if needed, like
520
+ * the Unix `touch` command.
521
+ *
522
+ * @param {string} path
523
+ * @returns {boolean}
66
524
  */
67
- export function deleteFolder(path: string): boolean | undefined;
525
+ export function touch(path: string): boolean;
68
526
  /**
69
- * Deletes files found inside a path.
70
- * @param {string} [path=process.cwd()] - The base path to inspect.
71
- * @param {boolean} [recursive=false] - Whether to scan recursively.
72
- * @param {(file: string) => boolean} [filter=() => true] - Filter applied to each file path.
73
- * @returns {number|undefined} Number of deleted files, or undefined if the path cannot be resolved.
527
+ * Deletes a folder and everything in it.
528
+ *
529
+ * @param {string} path
530
+ * @returns {boolean | undefined} `undefined` if it doesn't exist.
74
531
  */
75
- export function deleteFilesIn(path?: string, recursive?: boolean, filter?: (file: string) => boolean): number | undefined;
532
+ export function deleteFolder(path: string): boolean | undefined;
76
533
  /**
77
534
  * Deletes a file.
78
- * @param {string} path - The file path to delete.
79
- * @returns {boolean|undefined} True on success, false on failure, undefined if the path is invalid.
535
+ *
536
+ * @param {string} path
537
+ * @returns {boolean | undefined} `undefined` if it doesn't exist.
80
538
  */
81
539
  export function deleteFile(path: string): boolean | undefined;
82
540
  /**
83
- * Copies folders from a source path into a destination folder.
84
- * @param {Object} options - Copy options.
85
- * @param {string} options.dest - Destination path.
86
- * @param {string} [options.path] - Source path.
87
- * @param {boolean} [options.recursive=true] - Whether to recurse into subfolders.
88
- * @param {boolean} [options.withFiles=false] - Whether to copy files as well.
89
- * @param {boolean} [options.force=false] - Whether to overwrite existing folders.
90
- * @param {(folder: string) => boolean} [options.filter=() => true] - Filter applied to each folder.
91
- * @returns {number|undefined} Number of copied folders, or undefined if invalid input.
92
- */
93
- export function copyFoldersIn(options: {
94
- dest: string;
95
- path?: string | undefined;
96
- recursive?: boolean | undefined;
97
- withFiles?: boolean | undefined;
98
- force?: boolean | undefined;
99
- filter?: ((folder: string) => boolean) | undefined;
100
- }): number | undefined;
101
- /**
102
- * Copies a folder to a destination path.
103
- * @param {Object} options - Copy options.
104
- * @param {string} options.dest - Destination path.
105
- * @param {string} [options.path] - Source path.
106
- * @param {boolean} [options.recursive=false] - Whether to copy subfolders.
107
- * @param {boolean} [options.withFiles=false] - Whether to copy files.
108
- * @param {boolean} [options.force=false] - Whether to overwrite the destination.
109
- * @returns {boolean|undefined} True on success, false on failure, undefined if invalid input.
110
- */
111
- export function copyFolder(options: {
112
- dest: string;
113
- path?: string | undefined;
114
- recursive?: boolean | undefined;
115
- withFiles?: boolean | undefined;
116
- force?: boolean | undefined;
117
- }): boolean | undefined;
541
+ * Deletes a file or a folder, whichever it is. Nothing happens if the path
542
+ * doesn't exist.
543
+ *
544
+ * @example
545
+ * nc.remove("./dist");
546
+ *
547
+ * @param {string} path
548
+ * @returns {boolean} `true` if something was deleted.
549
+ */
550
+ export function remove(path: string): boolean;
118
551
  /**
119
- * Copies files from a source path into a destination folder.
120
- * @param {Object} options - Copy options.
121
- * @param {string} options.dest - Destination path.
122
- * @param {string} [options.path] - Source path.
123
- * @param {boolean} [options.recursive=true] - Whether to recurse into subfolders.
124
- * @param {boolean} [options.force=false] - Whether to overwrite existing files.
125
- * @param {(file: string) => boolean} [options.filter=() => true] - Filter applied to each file.
126
- * @returns {number|undefined} Number of copied files, or undefined if invalid input.
552
+ * Deletes the folders inside a folder that pass a test.
553
+ *
554
+ * @example
555
+ * nc.deleteFoldersIn("./packages", (folder) => folder.endsWith("dist"));
556
+ *
557
+ * @param {string} [path] Defaults to the working directory.
558
+ * @param {(folder: string) => boolean} [filter] Gets absolute paths. Defaults to every folder.
559
+ * @returns {number | undefined} How many were deleted.
127
560
  */
128
- export function copyFilesIn(options: {
129
- dest: string;
130
- path?: string | undefined;
131
- recursive?: boolean | undefined;
132
- force?: boolean | undefined;
133
- filter?: ((file: string) => boolean) | undefined;
134
- }): number | undefined;
561
+ export function deleteFoldersIn(path?: string, filter?: (folder: string) => boolean): number | undefined;
135
562
  /**
136
- * Copies a file to a destination path.
137
- * @param {Object} options - Copy options.
138
- * @param {string} options.path - Source file path.
139
- * @param {string} options.dest - Destination path.
140
- * @param {boolean} [options.force=false] - Whether to overwrite the destination file.
141
- * @returns {boolean|undefined} True on success, false on failure, undefined if invalid input.
563
+ * Deletes the files inside a folder that pass a test.
564
+ *
565
+ * @example
566
+ * nc.deleteFilesIn("./logs", false, (file) => file.endsWith(".log"));
567
+ *
568
+ * @param {string} [path] Defaults to the working directory.
569
+ * @param {boolean} [recursive=false]
570
+ * @param {(file: string) => boolean} [filter] Gets absolute paths. Defaults to every file.
571
+ * @returns {number | undefined} How many were deleted.
142
572
  */
143
- export function copyFile(options: {
144
- path: string;
145
- dest: string;
146
- force?: boolean | undefined;
147
- }): boolean | undefined;
573
+ export function deleteFilesIn(path?: string, recursive?: boolean, filter?: (file: string) => boolean): number | undefined;
148
574
  /**
149
- * Moves folders from a source path into a destination folder.
150
- * @param {Object} options - Move options.
151
- * @param {string} options.dest - Destination path.
152
- * @param {string} [options.path] - Source path.
153
- * @param {boolean} [options.recursive=true] - Whether to recurse into subfolders.
154
- * @param {boolean} [options.withFiles=false] - Whether to move files as well.
155
- * @param {boolean} [options.force=false] - Whether to overwrite existing folders.
156
- * @param {(folder: string) => boolean} [options.filter=() => true] - Filter applied to each folder.
157
- * @returns {number|undefined} Number of copied folders, or undefined if invalid input.
158
- */
159
- export function moveFoldersIn(options: {
160
- dest: string;
161
- path?: string | undefined;
162
- recursive?: boolean | undefined;
163
- withFiles?: boolean | undefined;
164
- force?: boolean | undefined;
165
- filter?: ((folder: string) => boolean) | undefined;
166
- }): number | undefined;
167
- /**
168
- * Moves a folder to a destination path.
169
- * @param {Object} options - Move options.
170
- * @param {string} options.path - Source folder path.
171
- * @param {string} options.dest - Destination path.
172
- * @param {boolean} [options.recursive=false] - Whether to move subfolders.
173
- * @param {boolean} [options.withFiles=false] - Whether to move files.
174
- * @param {boolean} [options.force=false] - Whether to overwrite the destination.
175
- * @returns {boolean|undefined} True on success, false on failure, undefined if invalid input.
176
- */
177
- export function moveFolder(options: {
178
- path: string;
179
- dest: string;
180
- recursive?: boolean | undefined;
181
- withFiles?: boolean | undefined;
182
- force?: boolean | undefined;
183
- }): boolean | undefined;
575
+ * Deletes everything inside a folder, keeping the folder.
576
+ *
577
+ * @param {string} path
578
+ * @returns {boolean | undefined} `undefined` if it doesn't exist.
579
+ */
580
+ export function emptyFolder(path: string): boolean | undefined;
184
581
  /**
185
- * Moves files from a source path into a destination folder.
186
- * @param {Object} options - Move options.
187
- * @param {string} options.dest - Destination path.
188
- * @param {string} [options.path] - Source path.
189
- * @param {boolean} [options.recursive=true] - Whether to recurse into subfolders.
190
- * @param {boolean} [options.force=false] - Whether to overwrite existing files.
191
- * @param {(file: string) => boolean} [options.filter=() => true] - Filter applied to each file.
192
- * @returns {number|undefined} Number of copied files, or undefined if invalid input.
582
+ * Copies a file or a whole folder, like `cp -r`.
583
+ *
584
+ * @example
585
+ * nc.copy("./templates", "./dist/templates");
586
+ * nc.copy("./.env.example", "./.env", { overwrite: false });
587
+ *
588
+ * @param {string} source
589
+ * @param {string} destination
590
+ * @param {CopyOptions} [options]
591
+ * @returns {boolean} `false` if the source is missing or the copy failed.
193
592
  */
194
- export function moveFilesIn(options: {
195
- dest: string;
196
- path?: string | undefined;
197
- recursive?: boolean | undefined;
198
- force?: boolean | undefined;
199
- filter?: ((file: string) => boolean) | undefined;
200
- }): number | undefined;
593
+ export function copy(source: string, destination: string, options?: CopyOptions): boolean;
594
+ /**
595
+ * Moves or renames a file or folder, across drives too.
596
+ *
597
+ * @example
598
+ * nc.move("./report.pdf", "./archive/2024/report.pdf");
599
+ *
600
+ * @param {string} source
601
+ * @param {string} destination
602
+ * @param {{ overwrite?: boolean }} [options] Replace an existing destination. Defaults to `true`.
603
+ * @returns {boolean}
604
+ */
605
+ export function move(source: string, destination: string, options?: {
606
+ overwrite?: boolean;
607
+ }): boolean;
608
+ /**
609
+ * Copies the folders inside a folder into another one. `copy()` is simpler
610
+ * for most cases.
611
+ *
612
+ * @param {CopyFoldersOptions} options
613
+ * @returns {number | undefined} How many were copied.
614
+ */
615
+ export function copyFoldersIn(options: CopyFoldersOptions): number | undefined;
616
+ /**
617
+ * Copies a folder. Without `recursive` or `withFiles`, only the empty
618
+ * folder is created; `copy()` copies everything in one call.
619
+ *
620
+ * @param {CopyFolderOptions} options
621
+ * @returns {boolean | undefined}
622
+ */
623
+ export function copyFolder(options: CopyFolderOptions): boolean | undefined;
624
+ /**
625
+ * Copies the files inside a folder into another one, keeping the tree.
626
+ *
627
+ * @example
628
+ * nc.copyFilesIn({ path: "./src", dest: "./dist", filter: (file) => file.endsWith(".css") });
629
+ *
630
+ * @param {CopyFilesOptions} options
631
+ * @returns {number | undefined} How many were copied.
632
+ */
633
+ export function copyFilesIn(options: CopyFilesOptions): number | undefined;
201
634
  /**
202
- * Moves a file to a destination path.
203
- * @param {Object} options - Move options.
204
- * @param {string} options.path - Source file path.
205
- * @param {string} options.dest - Destination path.
206
- * @param {boolean} [options.force=false] - Whether to overwrite the destination file.
207
- * @returns {boolean|undefined} True on success, false on failure, undefined if invalid input.
635
+ * Copies one file. If `dest` ends with `/`, the file keeps its name inside
636
+ * that folder.
637
+ *
638
+ * @example
639
+ * nc.copyFile({ path: "./src/index.js", dest: "./dist/" });
640
+ *
641
+ * @param {CopyFileOptions} options
642
+ * @returns {boolean | undefined}
208
643
  */
209
- export function moveFile(options: {
644
+ export function copyFile(options: CopyFileOptions): boolean | undefined;
645
+ /**
646
+ * Moves the folders inside a folder.
647
+ *
648
+ * @param {CopyFoldersOptions} options
649
+ * @returns {number | undefined} How many were moved.
650
+ */
651
+ export function moveFoldersIn(options: CopyFoldersOptions): number | undefined;
652
+ /**
653
+ * Moves a folder.
654
+ *
655
+ * @param {CopyFolderOptions & { path: string }} options
656
+ * @returns {boolean | undefined}
657
+ */
658
+ export function moveFolder(options: CopyFolderOptions & {
210
659
  path: string;
211
- dest: string;
212
- force?: boolean | undefined;
213
660
  }): boolean | undefined;
214
661
  /**
215
- * Reads a file as UTF-8 text.
216
- * @param {string} path - The file path to read.
217
- * @returns {string|undefined} File content, or undefined if the file cannot be read.
662
+ * Moves the files inside a folder.
663
+ *
664
+ * @param {CopyFilesOptions} options
665
+ * @returns {number | undefined} How many were moved.
218
666
  */
219
- export function readFile(path: string): string | undefined;
667
+ export function moveFilesIn(options: CopyFilesOptions): number | undefined;
220
668
  /**
221
- * Reads and parses a JSON file.
222
- * @template T
223
- * @param {string} path - The JSON file path.
224
- * @param {T} [fallback] - Value returned when the file is missing or invalid.
225
- * @returns {T|any|undefined} The parsed value, or the fallback.
669
+ * Moves one file.
670
+ *
671
+ * @example
672
+ * nc.moveFile({ path: "./logs/app.log", dest: "./logs/archive/" });
673
+ *
674
+ * @param {CopyFileOptions} options
675
+ * @returns {boolean | undefined}
226
676
  */
227
- export function readJSON<T>(path: string, fallback?: T): T | any | undefined;
677
+ export function moveFile(options: CopyFileOptions): boolean | undefined;
228
678
  /**
229
- * Serializes a value to JSON and writes it to a file (creating folders as needed).
230
- * @param {string} path - The destination file path.
231
- * @param {*} data - The value to serialize.
232
- * @param {{ spaces?: number, force?: boolean }} [options] - Formatting options (`spaces` default 2).
233
- * @returns {boolean} True on success, false on failure.
679
+ * Does a file or folder exist at this path?
680
+ *
681
+ * @param {string} path
682
+ * @returns {boolean}
234
683
  */
235
- export function writeJSON(path: string, data: any, options?: {
236
- spaces?: number;
237
- force?: boolean;
238
- }): boolean;
684
+ export function exists(path: string): boolean;
239
685
  /**
240
- * Appends text to a file, creating it (and its folders) if necessary.
241
- * @param {string} path - The file path.
242
- * @param {string} data - The text to append.
243
- * @returns {boolean} True on success, false on failure.
686
+ * Is it an existing file?
687
+ *
688
+ * @param {string} path
689
+ * @returns {boolean}
244
690
  */
245
- export function appendFile(path: string, data: string): boolean;
691
+ export function isFile(path: string): boolean;
246
692
  /**
247
- * Checks whether a path (file or folder) exists.
248
- * @param {string} path - The path to check.
249
- * @returns {boolean} True if the path exists.
693
+ * Is it an existing folder?
694
+ *
695
+ * @param {string} path
696
+ * @returns {boolean}
250
697
  */
251
- export function exists(path: string): boolean;
698
+ export function isFolder(path: string): boolean;
252
699
  /**
253
- * Returns filesystem stats for a path, or undefined if it does not exist.
254
- * @param {string} path - The path to stat.
255
- * @returns {import("node:fs").Stats|undefined} The stats object, or undefined.
700
+ * Size, dates and type of a path.
701
+ *
702
+ * @example
703
+ * nc.stat("./video.mp4")?.mtime;
704
+ *
705
+ * @param {string} path
706
+ * @returns {fs.Stats | undefined} `undefined` if it doesn't exist.
256
707
  */
257
- export function stat(path: string): any | undefined;
708
+ export function stat(path: string): fs.Stats | undefined;
258
709
  /**
259
- * Returns the size of a file in bytes.
260
- * @param {string} path - The file path.
261
- * @returns {number|undefined} Size in bytes, or undefined if not found.
710
+ * A file's size in bytes.
711
+ *
712
+ * @example
713
+ * nc.num.formatBytes(nc.fileSize("./backup.zip") ?? 0); // "1.2 GB"
714
+ *
715
+ * @param {string} path
716
+ * @returns {number | undefined} `undefined` if it doesn't exist.
262
717
  */
263
718
  export function fileSize(path: string): number | undefined;
264
719
  /**
265
- * Computes a hash digest of a file's contents.
266
- * @param {string} path - The file path.
267
- * @param {{ algorithm?: string, encoding?: "hex"|"base64"|"base64url" }} [options] - Hash options.
268
- * @returns {string|undefined} The digest, or undefined if the file cannot be read.
720
+ * The total size of every file in a folder.
721
+ *
722
+ * @param {string} path
723
+ * @returns {number | undefined} `undefined` if it doesn't exist.
724
+ */
725
+ export function folderSize(path: string): number | undefined;
726
+ /**
727
+ * Hashes a file in chunks, so huge files are fine.
728
+ *
729
+ * @example
730
+ * nc.hashFile("./release.zip"); // sha256, hex
731
+ * nc.hashFile("./release.zip", { algorithm: "md5" });
732
+ *
733
+ * @param {string} path
734
+ * @param {{ algorithm?: string, encoding?: "hex" | "base64" | "base64url" }} [options] Defaults to sha256 in hex.
735
+ * @returns {string | undefined} `undefined` if it can't be read.
269
736
  */
270
737
  export function hashFile(path: string, options?: {
271
738
  algorithm?: string;
272
739
  encoding?: "hex" | "base64" | "base64url";
273
740
  }): string | undefined;
274
741
  /**
275
- * Empties a folder's contents while keeping the folder itself.
276
- * @param {string} path - The folder to empty.
277
- * @returns {boolean|undefined} True on success, false on failure, undefined if not found.
742
+ * Creates a new, unique folder in the system's temp directory.
743
+ *
744
+ * @example
745
+ * const dir = nc.tempFolder("export-");
746
+ * try { await exportTo(dir); } finally { nc.remove(dir); }
747
+ *
748
+ * @param {string} [prefix="nc-"]
749
+ * @returns {string}
278
750
  */
279
- export function emptyFolder(path: string): boolean | undefined;
751
+ export function tempFolder(prefix?: string): string;
280
752
  /**
281
- * Watches a path and exposes event listeners.
282
- * @param {Object} [options] - Watch options.
283
- * @param {string} [options.path=process.cwd()] - Path to watch.
284
- * @param {boolean} [options.recursive=false] - Whether to watch recursively.
285
- * @param {(event: "rename"|"change", file: string) => boolean} [options.filter] - Filter applied before dispatch.
286
- * @returns {{
287
- * on: <E extends "change"|"rename"|"all">(event: E, callback: E extends "all" ? (event: "change"|"rename", file: string) => void|Promise<void> : (file: string) => void|Promise<void>) => any,
288
- * stop: () => void,
289
- * pause: () => any,
290
- * resume: () => any,
291
- * }|undefined} Watch controller, or undefined if the path cannot be resolved.
292
- */
293
- export function watch(options?: {
294
- path?: string | undefined;
295
- recursive?: boolean | undefined;
296
- filter?: ((event: "rename" | "change", file: string) => boolean) | undefined;
297
- }): {
298
- on: <E extends "change" | "rename" | "all">(event: E, callback: E extends "all" ? (event: "change" | "rename", file: string) => void | Promise<void> : (file: string) => void | Promise<void>) => any;
299
- stop: () => void;
300
- pause: () => any;
301
- resume: () => any;
302
- } | undefined;
753
+ * Turns any text into a file name that works on Windows, macOS and Linux:
754
+ * forbidden characters are replaced, reserved names like `CON` are
755
+ * prefixed, and the length is capped.
756
+ *
757
+ * @example
758
+ * nc.sanitizeFilename('Report: Q1/Q2 "final"?.pdf'); // "Report_ Q1_Q2 _final__.pdf"
759
+ * nc.sanitizeFilename("CON.txt"); // "_CON.txt"
760
+ *
761
+ * @param {string} name
762
+ * @param {{ replacement?: string }} [options] Defaults to `"_"`.
763
+ * @returns {string}
764
+ */
765
+ export function sanitizeFilename(name: string, options?: {
766
+ replacement?: string;
767
+ }): string;
768
+ /**
769
+ * Watches a file or folder for changes.
770
+ *
771
+ * @example
772
+ * const watcher = nc.watch({ path: "./src", recursive: true, debounce: 100 })
773
+ * .on("change", (file) => nc.info(`Changed: ${file}`))
774
+ * .on("rename", (file) => nc.info(`Added or removed: ${file}`));
775
+ * watcher.stop();
776
+ *
777
+ * @param {WatchOptions} [options]
778
+ * @returns {Watcher | undefined} `undefined` if the path doesn't exist.
779
+ */
780
+ export function watch(options?: WatchOptions): Watcher | undefined;
781
+ import fs = require("node:fs");
303
782
  //# sourceMappingURL=FS.d.ts.map