@ix-xs/node-comfort 1.0.3 → 1.0.5

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 (41) hide show
  1. package/index.js +12 -14
  2. package/package.json +17 -17
  3. package/src/checker.js +76 -0
  4. package/src/cli.js +86 -0
  5. package/{core/FS.js → src/fs.js} +121 -230
  6. package/src/localStorage.js +242 -0
  7. package/{core/Logger.js → src/logger.js} +23 -97
  8. package/src/utils.js +225 -0
  9. package/tsconfig.json +1 -1
  10. package/types/index.d.ts +73 -50
  11. package/types/src/checker.d.ts +49 -0
  12. package/types/src/checker.d.ts.map +1 -0
  13. package/types/src/cli.d.ts +26 -0
  14. package/types/src/cli.d.ts.map +1 -0
  15. package/types/src/fs.d.ts +210 -0
  16. package/types/src/fs.d.ts.map +1 -0
  17. package/types/src/localStorage.d.ts +97 -0
  18. package/types/src/localStorage.d.ts.map +1 -0
  19. package/types/src/logger.d.ts +132 -0
  20. package/types/src/logger.d.ts.map +1 -0
  21. package/types/src/utils.d.ts +92 -0
  22. package/types/src/utils.d.ts.map +1 -0
  23. package/core/CLI.js +0 -95
  24. package/core/Checker.js +0 -127
  25. package/core/Stepper.js +0 -115
  26. package/core/Storage.js +0 -348
  27. package/core/Utils.js +0 -206
  28. package/types/core/CLI.d.ts +0 -25
  29. package/types/core/CLI.d.ts.map +0 -1
  30. package/types/core/Checker.d.ts +0 -73
  31. package/types/core/Checker.d.ts.map +0 -1
  32. package/types/core/FS.d.ts +0 -211
  33. package/types/core/FS.d.ts.map +0 -1
  34. package/types/core/Logger.d.ts +0 -253
  35. package/types/core/Logger.d.ts.map +0 -1
  36. package/types/core/Stepper.d.ts +0 -49
  37. package/types/core/Stepper.d.ts.map +0 -1
  38. package/types/core/Storage.d.ts +0 -111
  39. package/types/core/Storage.d.ts.map +0 -1
  40. package/types/core/Utils.d.ts +0 -55
  41. package/types/core/Utils.d.ts.map +0 -1
@@ -1,39 +1,19 @@
1
- const dotenv = require("@dotenvx/dotenvx");
2
- const {
3
- readdirSync,
4
- existsSync,
5
- mkdirSync,
6
- rmSync,
7
- writeFileSync,
8
- unlinkSync,
9
- copyFileSync,
10
- readFileSync,
11
- watch,
12
- } = require("node:fs");
13
- const {
14
- resolve,
15
- dirname,
16
- sep,
17
- isAbsolute,
18
- join,
19
- relative,
20
- basename,
21
- } = require("node:path");
1
+ const { readdirSync, existsSync, mkdirSync, rmSync, writeFileSync, unlinkSync, copyFileSync, readFileSync, watch } = require("node:fs");
2
+ const { resolve, dirname, sep, isAbsolute, join, relative, basename } = require("node:path");
3
+
4
+ try {
5
+ process.loadEnvFile();
6
+ }
7
+ catch {}
22
8
 
23
9
  /**
24
- * Normalizes path separators for cross-platform compatibility.
25
- * @private
26
- * @param {string} path - Path to normalize.
27
- * @returns {string} Normalized path.
10
+ * @param {string} path
28
11
  */
29
12
  const _format = (path) => {
30
13
  return path.replace(/\//g, sep).replace(/\\/g, sep);
31
14
  };
32
-
33
15
  /**
34
- * Detects the caller's file path from stack trace (excludes node_modules/internal).
35
- * @private
36
- * @returns {string|undefined} Caller file path or undefined.
16
+ * @returns {string|undefined}
37
17
  */
38
18
  const _caller = () => {
39
19
  const opst = Error.prepareStackTrace;
@@ -47,9 +27,9 @@ const _caller = () => {
47
27
  const name = cs.getFileName();
48
28
  if (
49
29
  name &&
50
- !name.startsWith("node:internal") &&
51
- !name.includes("node_modules") &&
52
- name !== s[0].getFileName()
30
+ !name.startsWith("node:internal") &&
31
+ !name.includes("node_modules") &&
32
+ name !== s[0].getFileName()
53
33
  ) {
54
34
  return _format(name);
55
35
  }
@@ -57,14 +37,11 @@ const _caller = () => {
57
37
  }
58
38
  return undefined;
59
39
  };
60
-
61
40
  /**
62
- * Recursively walks directory returning files or folders.
63
- * @private
64
- * @param {string} path - Directory path.
65
- * @param {boolean} [recursive=true] - Include subdirectories.
66
- * @param {"folder"|"file"} [type="folder"] - Filter type.
67
- * @returns {string[]} Array of matching paths.
41
+ * @param {string} path
42
+ * @param {boolean} [recursive=true]
43
+ * @param {"folder"|"file"} [type="folder"]
44
+ * @returns {string[]}
68
45
  */
69
46
  const _walk = (path = process.cwd(), recursive = true, type = "folder") => {
70
47
  let result = [];
@@ -87,13 +64,10 @@ const _walk = (path = process.cwd(), recursive = true, type = "folder") => {
87
64
  return result;
88
65
  }
89
66
  };
90
-
91
67
  /**
92
- * Finds first matching folder recursively from root.
93
- * @private
94
- * @param {string} path - Starting path.
95
- * @param {string} name - Folder name to find.
96
- * @returns {string|undefined} First matching folder path.
68
+ * @param {string} path
69
+ * @param {string} name
70
+ * @returns {string|undefined}
97
71
  */
98
72
  const _firstFolder = (path, name) => {
99
73
  try {
@@ -112,13 +86,10 @@ const _firstFolder = (path, name) => {
112
86
  } catch {}
113
87
  return undefined;
114
88
  };
115
-
116
89
  /**
117
- * Finds first matching file recursively from root.
118
- * @private
119
- * @param {string} path - Starting path.
120
- * @param {string} name - File name to find.
121
- * @returns {string|undefined} First matching file path.
90
+ * @param {string} path
91
+ * @param {string} name
92
+ * @returns {string|undefined}
122
93
  */
123
94
  const _firstFile = (path, name) => {
124
95
  try {
@@ -137,13 +108,10 @@ const _firstFile = (path, name) => {
137
108
  } catch {}
138
109
  return undefined;
139
110
  };
140
-
141
111
  /**
142
- * Resolves target path with smart relative/absolute/caller context detection.
143
- * @private
144
- * @param {string} [path=process.cwd()] - Path to resolve.
145
- * @param {"folder"|"file"} [type="folder"] - Resolution type.
146
- * @returns {string|undefined} Resolved absolute path or undefined.
112
+ * @param {string} [path=process.cwd()]
113
+ * @param {"folder"|"file"} [type="folder"]
114
+ * @returns {string|undefined}
147
115
  */
148
116
  const _target = (path = process.cwd(), type = "folder") => {
149
117
  if (path === process.cwd()) return path;
@@ -153,7 +121,7 @@ const _target = (path = process.cwd(), type = "folder") => {
153
121
 
154
122
  if (
155
123
  _format(path).startsWith(_format("./")) ||
156
- _format(path).startsWith(_format("../"))
124
+ _format(path).startsWith(_format("../"))
157
125
  ) {
158
126
  absolute = resolve(caller, path);
159
127
  } else if (isAbsolute(path)) {
@@ -162,9 +130,9 @@ const _target = (path = process.cwd(), type = "folder") => {
162
130
  absolute = resolve(process.cwd(), _format(path));
163
131
  if (!existsSync(absolute)) {
164
132
  absolute =
165
- type === "folder"
166
- ? (_firstFolder(process.cwd(), _format(path)) ?? undefined)
167
- : (_firstFile(process.cwd(), _format(path)) ?? undefined);
133
+ type === "folder"
134
+ ? (_firstFolder(process.cwd(), _format(path)) ?? undefined)
135
+ : (_firstFile(process.cwd(), _format(path)) ?? undefined);
168
136
  }
169
137
  }
170
138
 
@@ -172,58 +140,15 @@ const _target = (path = process.cwd(), type = "folder") => {
172
140
  return undefined;
173
141
  };
174
142
 
175
- /**
176
- * @module FS
177
- * @description
178
- * Comprehensive synchronous file system utilities with intelligent path resolution,
179
- * caller context awareness, and cross-platform support.
180
- *
181
- * Handles relative/absolute paths relative to caller file, recursive operations,
182
- * file/folder watching, and bulk copy/move operations. Automatically skips `node_modules`.
183
- *
184
- * @example
185
- * const nodeComfort = require("@ix-xs/node-comfort");
186
- *
187
- * // Create folder structure
188
- * nodeComfort.createFolder("./data/users");
189
- *
190
- * // Write JSON file
191
- * nodeComfort.createFile("./data/users.json", false, { users: [] });
192
- *
193
- * // List all files recursively
194
- * console.log(nodeComfort.getFilesIn("./data"));
195
- *
196
- * // Watch for changes
197
- * const watcher = nodeComfort.watch({ path: "./data", recursive: true });
198
- * watcher.on("change", (file) => console.log("File changed:", file));
199
- */
200
143
  module.exports = {
201
144
  /**
202
- * Safely read an environment variable.
203
- *
204
- * Loads variables from the default `.env` file (if present) and then
205
- * returns the value for the given key. When `options.envFile` is provided,
206
- * the function expects `process.env[options.envFile]` to be an object
207
- * containing namespaced environment variables (e.g. per environment).
208
- *
209
- * @param {string} env - Environment variable name (e.g. "PORT").
210
- * @param {object} [options] - Optional configuration object.
211
- * @param {string} [options.envFile] - Name of a namespaced env container under `process.env`.
212
- * @returns {string|undefined} The environment variable value, or `undefined` if not found.
213
- */
214
- getEnv(env, options) {
215
- dotenv.config({ quiet: true });
216
- return options?.envFile
217
- ? process.env[options?.envFile][env]
218
- : process.env[env];
145
+ * @param {string} value
146
+ */
147
+ getEnv(value, envFilePath) {
148
+ return process.env[value];
219
149
  },
220
150
  /**
221
- * Resolves path relative to caller file or current directory.
222
- * Supports `./`, `../`, absolute paths, and searches for existing paths.
223
- * @param {string} [path=process.cwd()] - Path to resolve.
224
- * @returns {string} Resolved absolute path.
225
- * @example
226
- * nodeComfort.createPath("./data/users"); // Resolves from caller file
151
+ * @param {string} [path=process.cwd()]
227
152
  */
228
153
  createPath(path = process.cwd()) {
229
154
  const target = _target(path);
@@ -235,52 +160,37 @@ module.exports = {
235
160
  ? resolve(dirname(_caller()), path)
236
161
  : resolve(process.cwd(), path);
237
162
  },
238
-
239
163
  /**
240
- * Returns all folders in path (recursive option).
241
- * @param {string} [path=process.cwd()] - Starting directory.
242
- * @param {boolean} [recursive=true] - Include subfolders.
243
- * @returns {string[]|undefined} Array of folder paths.
164
+ * @param {string} [path]
165
+ * @param {boolean} [recursive]
244
166
  */
245
167
  getFoldersIn(path = process.cwd(), recursive = true) {
246
168
  const target = _target(path ?? process.cwd());
247
169
  return target ? _walk(target, recursive) : undefined;
248
170
  },
249
-
250
171
  /**
251
- * Resolves and returns existing folder path.
252
- * @param {string} [path=process.cwd()] - Folder path.
253
- * @returns {string|undefined} Absolute folder path.
172
+ * @param {string} [path]
254
173
  */
255
174
  getFolder(path = process.cwd()) {
256
175
  return _target(path ?? process.cwd());
257
176
  },
258
-
259
177
  /**
260
- * Returns all files in path (recursive option).
261
- * @param {string} [path=process.cwd()] - Starting directory.
262
- * @param {boolean} [recursive=true] - Include subdirectories.
263
- * @returns {string[]|undefined} Array of file paths.
178
+ * @param {string} [path]
179
+ * @param {boolean} [recursive]
264
180
  */
265
181
  getFilesIn(path = process.cwd(), recursive = true) {
266
182
  const target = _target(path ?? process.cwd());
267
183
  return target ? _walk(target, recursive, "file") : undefined;
268
184
  },
269
-
270
185
  /**
271
- * Resolves and returns existing file path.
272
- * @param {string} path - File path.
273
- * @returns {string|undefined} Absolute file path.
186
+ * @param {string} path
274
187
  */
275
188
  getFile(path) {
276
189
  return path ? _target(path, "file") : path;
277
190
  },
278
-
279
191
  /**
280
- * Creates folder (recursive) with force overwrite option.
281
- * @param {string} path - Folder path to create.
282
- * @param {boolean} [force=false] - Overwrite if exists.
283
- * @returns {boolean|undefined} Success status.
192
+ * @param {string} path
193
+ * @param {boolean} [force]
284
194
  */
285
195
  createFolder(path, force = false) {
286
196
  if (!path) return undefined;
@@ -301,16 +211,10 @@ module.exports = {
301
211
  return false;
302
212
  }
303
213
  },
304
-
305
214
  /**
306
- * Creates file with auto-directory creation and content serialization.
307
- * Supports string, object (→ JSON), null/undefined (→ empty).
308
- * @param {string} path - File path.
309
- * @param {boolean} [force=false] - Overwrite if exists.
310
- * @param {string|object|null|undefined} [data] - File content.
311
- * @returns {boolean|undefined} Success status.
312
- * @example
313
- * nodeComfort.createFile("config.json", false, { apiKey: "secret" });
215
+ * @param {string} path
216
+ * @param {boolean} [force]
217
+ * @param {string|object|null|undefined} [data]
314
218
  */
315
219
  createFile(path, force = false, data) {
316
220
  if (!path) return undefined;
@@ -342,12 +246,9 @@ module.exports = {
342
246
  return false;
343
247
  }
344
248
  },
345
-
346
249
  /**
347
- * Deletes multiple folders matching filter.
348
- * @param {string} [path=process.cwd()] - Starting directory.
349
- * @param {(folder: string) => boolean} [filter] - Folder filter function.
350
- * @returns {number|undefined} Count of deleted folders.
250
+ * @param {string} [path]
251
+ * @param {(folder: string) => boolean} [filter]
351
252
  */
352
253
  deleteFoldersIn(path = process.cwd(), filter = () => true) {
353
254
  const target = _target(path);
@@ -363,11 +264,8 @@ module.exports = {
363
264
  }
364
265
  return deleted;
365
266
  },
366
-
367
267
  /**
368
- * Deletes folder and all contents recursively.
369
- * @param {string} path - Folder path.
370
- * @returns {boolean|undefined} Success status.
268
+ * @param {string} path
371
269
  */
372
270
  deleteFolder(path) {
373
271
  const target = path ? _target(path) : path;
@@ -380,13 +278,10 @@ module.exports = {
380
278
  return false;
381
279
  }
382
280
  },
383
-
384
281
  /**
385
- * Deletes multiple files matching filter.
386
- * @param {string} [path=process.cwd()] - Starting directory.
387
- * @param {boolean} [recursive=false] - Search subdirectories.
388
- * @param {(file: string) => boolean} [filter] - File filter function.
389
- * @returns {number|undefined} Count of deleted files.
282
+ * @param {string} [path=process.cwd()]
283
+ * @param {boolean} [recursive=false]
284
+ * @param {(file: string) => boolean} [filter]
390
285
  */
391
286
  deleteFilesIn(path = process.cwd(), recursive = false, filter = () => true) {
392
287
  const target = _target(path);
@@ -402,11 +297,8 @@ module.exports = {
402
297
  }
403
298
  return deleted;
404
299
  },
405
-
406
300
  /**
407
- * Deletes single file.
408
- * @param {string} path - File path.
409
- * @returns {boolean|undefined} Success status.
301
+ * @param {string} path
410
302
  */
411
303
  deleteFile(path) {
412
304
  const target = path ? _target(path, "file") : path;
@@ -419,17 +311,14 @@ module.exports = {
419
311
  return false;
420
312
  }
421
313
  },
422
-
423
314
  /**
424
- * Copies multiple folders with optional files and recursive support.
425
- * @param {Object} options - Copy options.
426
- * @param {string} options.dest - Destination base path.
427
- * @param {string} [options.path] - Source path.
428
- * @param {boolean} [options.recursive=true] - Copy subfolders.
429
- * @param {boolean} [options.withFiles=false] - Include files.
430
- * @param {boolean} [options.force=false] - Overwrite existing.
431
- * @param {(folder: string) => boolean} [options.filter] - Folder filter.
432
- * @returns {number|undefined} Count of copied folders.
315
+ * @param {Object} options
316
+ * @param {string} options.dest
317
+ * @param {string} [options.path]
318
+ * @param {boolean} [options.recursive=true]
319
+ * @param {boolean} [options.withFiles=false]
320
+ * @param {boolean} [options.force=false]
321
+ * @param {(folder: string) => boolean} [options.filter]
433
322
  */
434
323
  copyFoldersIn(options) {
435
324
  const target = _target(options.path ?? process.cwd());
@@ -472,16 +361,13 @@ module.exports = {
472
361
  }
473
362
  return copied;
474
363
  },
475
-
476
364
  /**
477
- * Copies single folder with optional contents.
478
- * @param {Object} options - Copy options.
479
- * @param {string} options.dest - Destination path.
480
- * @param {string} [options.path] - Source path.
481
- * @param {boolean} [options.recursive=false] - Copy subfolders.
482
- * @param {boolean} [options.withFiles=false] - Include files.
483
- * @param {boolean} [options.force=false] - Overwrite existing.
484
- * @returns {boolean|undefined} Success status.
365
+ * @param {Object} options
366
+ * @param {string} options.dest
367
+ * @param {string} [options.path]
368
+ * @param {boolean} [options.recursive=false]
369
+ * @param {boolean} [options.withFiles=false]
370
+ * @param {boolean} [options.force=false]
485
371
  */
486
372
  copyFolder(options) {
487
373
  const target = _target(options.path ?? process.cwd());
@@ -524,16 +410,13 @@ module.exports = {
524
410
  }
525
411
  return true;
526
412
  },
527
-
528
413
  /**
529
- * Copies multiple files with optional recursive structure preservation.
530
- * @param {Object} options - Copy options.
531
- * @param {string} options.dest - Destination base path.
532
- * @param {string} [options.path] - Source path.
533
- * @param {boolean} [options.recursive=true] - Preserve directory structure.
534
- * @param {boolean} [options.force=false] - Overwrite existing.
535
- * @param {(file: string) => boolean} [options.filter] - File filter.
536
- * @returns {number|undefined} Count of copied files.
414
+ * @param {Object} options
415
+ * @param {string} options.dest
416
+ * @param {string} [options.path]
417
+ * @param {boolean} [options.recursive=true]
418
+ * @param {boolean} [options.force=false]
419
+ * @param {(file: string) => boolean} [options.filter]
537
420
  */
538
421
  copyFilesIn(options) {
539
422
  const target = _target(options.path ?? process.cwd());
@@ -565,14 +448,11 @@ module.exports = {
565
448
  }
566
449
  return copied;
567
450
  },
568
-
569
451
  /**
570
- * Copies single file to destination (auto-creates parent folders).
571
- * @param {Object} options - Copy options.
572
- * @param {string} options.path - Source file path.
573
- * @param {string} options.dest - Destination path or folder.
574
- * @param {boolean} [options.force=false] - Overwrite existing.
575
- * @returns {boolean|undefined} Success status.
452
+ * @param {Object} options
453
+ * @param {string} options.path
454
+ * @param {string} options.dest
455
+ * @param {boolean} [options.force=false]
576
456
  */
577
457
  copyFile(options) {
578
458
  const target = _target(options.path, "file");
@@ -597,11 +477,14 @@ module.exports = {
597
477
  copyFileSync(target, destFile);
598
478
  return true;
599
479
  },
600
-
601
480
  /**
602
- * Moves multiple folders (copy + delete source).
603
- * @param {Object} options - Move options (same as copyFoldersIn).
604
- * @returns {number|undefined} Count of moved folders.
481
+ * @param {Object} options
482
+ * @param {string} options.dest
483
+ * @param {string} [options.path]
484
+ * @param {boolean} [options.recursive=true]
485
+ * @param {boolean} [options.withFiles=false]
486
+ * @param {boolean} [options.force=false]
487
+ * @param {(folder: string) => boolean} [options.filter]
605
488
  */
606
489
  moveFoldersIn(options) {
607
490
  const copied = this.copyFoldersIn(options);
@@ -620,11 +503,13 @@ module.exports = {
620
503
  }
621
504
  return copied;
622
505
  },
623
-
624
506
  /**
625
- * Moves single folder (copy + delete source).
626
- * @param {Object} options - Move options (same as copyFolder).
627
- * @returns {boolean|undefined} Success status.
507
+ * @param {Object} options
508
+ * @param {string} options.path
509
+ * @param {string} options.dest
510
+ * @param {boolean} [options.recursive=false]
511
+ * @param {boolean} [options.withFiles=false]
512
+ * @param {boolean} [options.force=false]
628
513
  */
629
514
  moveFolder(options) {
630
515
  const copied = this.copyFolder(options);
@@ -634,11 +519,13 @@ module.exports = {
634
519
  this.deleteFolder(target);
635
520
  return copied;
636
521
  },
637
-
638
522
  /**
639
- * Moves multiple files (copy + delete source).
640
- * @param {Object} options - Move options (same as copyFilesIn).
641
- * @returns {number|undefined} Count of moved files.
523
+ * @param {Object} options
524
+ * @param {string} options.dest
525
+ * @param {string} [options.path]
526
+ * @param {boolean} [options.recursive=true]
527
+ * @param {boolean} [options.force=false]
528
+ * @param {(file: string) => boolean} [options.filter]
642
529
  */
643
530
  moveFilesIn(options) {
644
531
  const copied = this.copyFilesIn(options);
@@ -657,11 +544,11 @@ module.exports = {
657
544
  }
658
545
  return copied;
659
546
  },
660
-
661
547
  /**
662
- * Moves single file (copy + delete source).
663
- * @param {Object} options - Move options (same as copyFile).
664
- * @returns {boolean|undefined} Success status.
548
+ * @param {Object} options
549
+ * @param {string} options.path
550
+ * @param {string} options.dest
551
+ * @param {boolean} [options.force=false]
665
552
  */
666
553
  moveFile(options) {
667
554
  const moved = this.copyFile(options);
@@ -671,11 +558,8 @@ module.exports = {
671
558
  }
672
559
  return moved;
673
560
  },
674
-
675
561
  /**
676
- * Reads file content synchronously.
677
- * @param {string} path - File path.
678
- * @returns {string|undefined} File content or undefined.
562
+ * @param {string} path
679
563
  */
680
564
  readFile(path) {
681
565
  const target = _target(path, "file");
@@ -687,19 +571,11 @@ module.exports = {
687
571
  return undefined;
688
572
  }
689
573
  },
690
-
691
574
  /**
692
- * Creates file system watcher with event filtering and pause/resume.
693
- * @param {Object} [options] - Watcher options.
694
- * @param {string} [options.path=process.cwd()] - Watch path.
695
- * @param {boolean} [options.recursive=false] - Watch subdirectories.
696
- * @param {(event: string, file: string) => boolean} [options.filter] - Event filter.
697
- * @returns {Object|undefined} Watcher API.
698
- * @example
699
- * const watcher = nodeComfort.watch({ path: "./src", recursive: true });
700
- * watcher.on("change", (file) => console.log("Changed:", file));
701
- * watcher.on("rename", (file) => console.log("Renamed:", file));
702
- * watcher.on("all", (event, file) => console.log(event, file));
575
+ * @param {Object} [options]
576
+ * @param {string} [options.path=process.cwd()]
577
+ * @param {boolean} [options.recursive=false]
578
+ * @param {(event: string, file: string) => boolean} [options.filter]
703
579
  */
704
580
  watch(options = {}) {
705
581
  const target = _target(options.path ?? process.cwd());
@@ -708,6 +584,10 @@ module.exports = {
708
584
  let paused = false;
709
585
  const listeners = {};
710
586
 
587
+ /**
588
+ * @param {"rename"|"change"|"all"} event
589
+ * @param {string} file
590
+ */
711
591
  const handler = (event, file) => {
712
592
  if (paused) return;
713
593
  if (
@@ -740,12 +620,21 @@ module.exports = {
740
620
 
741
621
  return {
742
622
  /**
743
- * Adds event listener.
744
- * @param {"change"|"rename"|"all"} event - Event type.
745
- * @param {function} callback - Callback function.
623
+ * @typedef { "change" | "rename" | "all" } EventNames
624
+ * @typedef {{
625
+ * change: (file: string) => void|Promise<void>,
626
+ * rename: (file: string) => void|Promise<void>,
627
+ * all: (event: EventNames, file: string) => void|Promise<void>,
628
+ * }} EventHandlers
629
+ */
630
+ /**
631
+ * @template {EventNames} E
632
+ * @param {E} event
633
+ * @param {EventHandlers[E]} callback
746
634
  */
747
635
  on(event, callback) {
748
636
  addListener(event, callback);
637
+ return this;
749
638
  },
750
639
  stop() {
751
640
  if (watcher) {
@@ -756,9 +645,11 @@ module.exports = {
756
645
  },
757
646
  pause() {
758
647
  paused = true;
648
+ return this;
759
649
  },
760
650
  resume() {
761
651
  paused = false;
652
+ return this;
762
653
  },
763
654
  };
764
655
  },