@thi.ng/file-io 1.1.5 → 1.2.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/CHANGELOG.md +11 -1
- package/README.md +1 -1
- package/files.js +1 -4
- package/index.d.ts +1 -0
- package/index.js +1 -0
- package/package.json +9 -6
- package/watch.d.ts +41 -0
- package/watch.js +119 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Change Log
|
|
2
2
|
|
|
3
|
-
- **Last updated**: 2024-01-
|
|
3
|
+
- **Last updated**: 2024-01-26T18:03:04Z
|
|
4
4
|
- **Generator**: [thi.ng/monopub](https://thi.ng/monopub)
|
|
5
5
|
|
|
6
6
|
All notable changes to this project will be documented in this file.
|
|
@@ -9,6 +9,16 @@ See [Conventional Commits](https://conventionalcommits.org/) for commit guidelin
|
|
|
9
9
|
**Note:** Unlisted _patch_ versions only involve non-code or otherwise excluded changes
|
|
10
10
|
and/or version bumps of transitive dependencies.
|
|
11
11
|
|
|
12
|
+
## [1.2.0](https://github.com/thi-ng/umbrella/tree/@thi.ng/file-io@1.2.0) (2024-01-26)
|
|
13
|
+
|
|
14
|
+
#### 🚀 Features
|
|
15
|
+
|
|
16
|
+
- add fileWatcher() ([71c1d8f](https://github.com/thi-ng/umbrella/commit/71c1d8f))
|
|
17
|
+
|
|
18
|
+
#### ♻️ Refactoring
|
|
19
|
+
|
|
20
|
+
- migrate internal predicates ([52c985a](https://github.com/thi-ng/umbrella/commit/52c985a))
|
|
21
|
+
|
|
12
22
|
## [1.1.0](https://github.com/thi-ng/umbrella/tree/@thi.ng/file-io@1.1.0) (2023-12-18)
|
|
13
23
|
|
|
14
24
|
#### 🚀 Features
|
package/README.md
CHANGED
package/files.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import { isFunction } from "@thi.ng/checks/is-function";
|
|
2
|
-
import { isString } from "@thi.ng/checks/is-string";
|
|
3
1
|
import { readdirSync, statSync } from "fs";
|
|
4
2
|
import { sep } from "path";
|
|
5
3
|
import { isDirectory } from "./dir.js";
|
|
4
|
+
import { __ensurePred } from "./internal/ensure.js";
|
|
6
5
|
const files = (dir, match = "", maxDepth = Infinity, logger) => __files(dir, match, logger, maxDepth, 0);
|
|
7
6
|
function* __files(dir, match = "", logger, maxDepth = Infinity, depth = 0) {
|
|
8
7
|
if (depth >= maxDepth)
|
|
@@ -39,8 +38,6 @@ function* __dirs(dir, match = "", logger, maxDepth = Infinity, depth = 0) {
|
|
|
39
38
|
}
|
|
40
39
|
}
|
|
41
40
|
}
|
|
42
|
-
const __ensureRegEx = (match) => isString(match) ? new RegExp(`${match.replace(/\./g, "\\.")}$`) : match;
|
|
43
|
-
const __ensurePred = (match) => isFunction(match) ? match : (match = __ensureRegEx(match), (x) => match.test(x));
|
|
44
41
|
export {
|
|
45
42
|
dirs,
|
|
46
43
|
files
|
package/index.d.ts
CHANGED
package/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thi.ng/file-io",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "Assorted file I/O utils (with logging support) for NodeJS",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"module": "./index.js",
|
|
@@ -35,11 +35,11 @@
|
|
|
35
35
|
"test": "bun test"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@thi.ng/api": "^8.9.
|
|
39
|
-
"@thi.ng/checks": "^3.4.
|
|
40
|
-
"@thi.ng/hex": "^2.3.
|
|
38
|
+
"@thi.ng/api": "^8.9.18",
|
|
39
|
+
"@thi.ng/checks": "^3.4.18",
|
|
40
|
+
"@thi.ng/hex": "^2.3.30",
|
|
41
41
|
"@thi.ng/logger": "^2.1.4",
|
|
42
|
-
"@thi.ng/random": "^3.6.
|
|
42
|
+
"@thi.ng/random": "^3.6.25"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
45
|
"@microsoft/api-extractor": "^7.39.0",
|
|
@@ -108,6 +108,9 @@
|
|
|
108
108
|
"./text": {
|
|
109
109
|
"default": "./text.js"
|
|
110
110
|
},
|
|
111
|
+
"./watch": {
|
|
112
|
+
"default": "./watch.js"
|
|
113
|
+
},
|
|
111
114
|
"./write": {
|
|
112
115
|
"default": "./write.js"
|
|
113
116
|
}
|
|
@@ -116,5 +119,5 @@
|
|
|
116
119
|
"status": "stable",
|
|
117
120
|
"year": 2022
|
|
118
121
|
},
|
|
119
|
-
"gitHead": "
|
|
122
|
+
"gitHead": "7426e2ae6fca5482c6eaf649872296fc89955374\n"
|
|
120
123
|
}
|
package/watch.d.ts
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { type Event, type IClear, type INotify, type IObjectOf, type Listener, type Predicate } from "@thi.ng/api";
|
|
3
|
+
import type { ILogger } from "@thi.ng/logger";
|
|
4
|
+
import { type FSWatcher } from "fs";
|
|
5
|
+
export interface WatcherOpts {
|
|
6
|
+
/**
|
|
7
|
+
* Number of milliseconds between observing a file change and notifying
|
|
8
|
+
* attached listeners.
|
|
9
|
+
*
|
|
10
|
+
* @defaultValue 100
|
|
11
|
+
*/
|
|
12
|
+
delay: number;
|
|
13
|
+
/**
|
|
14
|
+
* Logger instance for showing debug info (must have DEBUG level enabled)
|
|
15
|
+
*/
|
|
16
|
+
logger: ILogger;
|
|
17
|
+
}
|
|
18
|
+
export interface PathWatchOpts {
|
|
19
|
+
recursive: boolean;
|
|
20
|
+
ext: string | RegExp | Predicate<string>;
|
|
21
|
+
}
|
|
22
|
+
export declare const EVENT_ADDED = "added";
|
|
23
|
+
export declare const EVENT_CHANGED = "changed";
|
|
24
|
+
export declare const EVENT_REMOVED = "removed";
|
|
25
|
+
export declare class Watcher implements IClear, INotify {
|
|
26
|
+
watchers: IObjectOf<FSWatcher>;
|
|
27
|
+
opts: WatcherOpts;
|
|
28
|
+
protected _signal: boolean;
|
|
29
|
+
constructor(opts?: Partial<WatcherOpts>);
|
|
30
|
+
addAll(paths: (string | [string, Partial<PathWatchOpts>])[]): void;
|
|
31
|
+
add(path: string, opts?: Partial<PathWatchOpts>): boolean;
|
|
32
|
+
remove(path: string): boolean;
|
|
33
|
+
removeAll(paths: Iterable<string>): void;
|
|
34
|
+
clear(): void;
|
|
35
|
+
installSignalHandler(): void;
|
|
36
|
+
addListener(id: string, fn: Listener<string>, scope?: any): boolean;
|
|
37
|
+
removeListener(id: string, fn: Listener<string>, scope?: any): boolean;
|
|
38
|
+
notify(event: Event<string>): boolean;
|
|
39
|
+
}
|
|
40
|
+
export declare const fileWatcher: (opts?: Partial<WatcherOpts>) => Watcher;
|
|
41
|
+
//# sourceMappingURL=watch.d.ts.map
|
package/watch.js
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
+
var __decorateClass = (decorators, target, key, kind) => {
|
|
4
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
|
|
5
|
+
for (var i = decorators.length - 1, decorator; i >= 0; i--)
|
|
6
|
+
if (decorator = decorators[i])
|
|
7
|
+
result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
|
8
|
+
if (kind && result)
|
|
9
|
+
__defProp(target, key, result);
|
|
10
|
+
return result;
|
|
11
|
+
};
|
|
12
|
+
import {
|
|
13
|
+
INotifyMixin
|
|
14
|
+
} from "@thi.ng/api";
|
|
15
|
+
import { isString } from "@thi.ng/checks/is-string";
|
|
16
|
+
import { NULL_LOGGER } from "@thi.ng/logger/null";
|
|
17
|
+
import { watch as $watch, existsSync } from "fs";
|
|
18
|
+
import { join } from "path";
|
|
19
|
+
import { isDirectory } from "./dir.js";
|
|
20
|
+
import { __ensurePred } from "./internal/ensure.js";
|
|
21
|
+
const EVENT_ADDED = "added";
|
|
22
|
+
const EVENT_CHANGED = "changed";
|
|
23
|
+
const EVENT_REMOVED = "removed";
|
|
24
|
+
let Watcher = class {
|
|
25
|
+
watchers = {};
|
|
26
|
+
opts;
|
|
27
|
+
_signal = false;
|
|
28
|
+
constructor(opts) {
|
|
29
|
+
this.opts = {
|
|
30
|
+
logger: NULL_LOGGER,
|
|
31
|
+
delay: 100,
|
|
32
|
+
...opts
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
addAll(paths) {
|
|
36
|
+
for (let p of paths) {
|
|
37
|
+
isString(p) ? this.add(p) : this.add(...p);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
add(path, opts) {
|
|
41
|
+
if (this.watchers[path])
|
|
42
|
+
return false;
|
|
43
|
+
const isDir = isDirectory(path);
|
|
44
|
+
const pred = __ensurePred(opts?.ext || "");
|
|
45
|
+
this.opts.logger.debug(`adding watcher for: ${path}`);
|
|
46
|
+
this.watchers[path] = $watch(
|
|
47
|
+
path,
|
|
48
|
+
{ recursive: opts?.recursive !== false },
|
|
49
|
+
(event, currPath) => {
|
|
50
|
+
if (!currPath)
|
|
51
|
+
return;
|
|
52
|
+
currPath = isDir ? join(path, currPath) : path;
|
|
53
|
+
if (!pred(currPath))
|
|
54
|
+
return;
|
|
55
|
+
setTimeout(() => {
|
|
56
|
+
if (event === "change") {
|
|
57
|
+
this.opts.logger.info(`file changed: ${currPath}`);
|
|
58
|
+
this.notify({
|
|
59
|
+
id: EVENT_CHANGED,
|
|
60
|
+
value: currPath
|
|
61
|
+
});
|
|
62
|
+
} else if (!isDir || path === currPath) {
|
|
63
|
+
this.opts.logger.info(`file removed: ${path}`);
|
|
64
|
+
this.notify({ id: EVENT_REMOVED, value: path });
|
|
65
|
+
this.remove(path);
|
|
66
|
+
} else {
|
|
67
|
+
const id = existsSync(currPath) ? EVENT_ADDED : EVENT_REMOVED;
|
|
68
|
+
this.opts.logger.info(`file ${id}: ${path}`);
|
|
69
|
+
this.notify({ id, value: currPath });
|
|
70
|
+
}
|
|
71
|
+
}, this.opts.delay);
|
|
72
|
+
}
|
|
73
|
+
);
|
|
74
|
+
return true;
|
|
75
|
+
}
|
|
76
|
+
remove(path) {
|
|
77
|
+
const watcher = this.watchers[path];
|
|
78
|
+
if (!watcher)
|
|
79
|
+
return false;
|
|
80
|
+
this.opts.logger.debug(`removing watcher for: ${path}`);
|
|
81
|
+
watcher.close();
|
|
82
|
+
delete this.watchers[path];
|
|
83
|
+
return true;
|
|
84
|
+
}
|
|
85
|
+
removeAll(paths) {
|
|
86
|
+
for (let p of paths) {
|
|
87
|
+
this.remove(p);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
clear() {
|
|
91
|
+
this.removeAll(Object.keys(this.watchers));
|
|
92
|
+
}
|
|
93
|
+
installSignalHandler() {
|
|
94
|
+
if (!this._signal) {
|
|
95
|
+
process.on("SIGINT", () => this.clear());
|
|
96
|
+
this._signal = true;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
// @ts-ignore mixin
|
|
100
|
+
addListener(id, fn, scope) {
|
|
101
|
+
}
|
|
102
|
+
// @ts-ignore mixin
|
|
103
|
+
removeListener(id, fn, scope) {
|
|
104
|
+
}
|
|
105
|
+
// @ts-ignore mixin
|
|
106
|
+
notify(event) {
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
Watcher = __decorateClass([
|
|
110
|
+
INotifyMixin
|
|
111
|
+
], Watcher);
|
|
112
|
+
const fileWatcher = (opts) => new Watcher(opts);
|
|
113
|
+
export {
|
|
114
|
+
EVENT_ADDED,
|
|
115
|
+
EVENT_CHANGED,
|
|
116
|
+
EVENT_REMOVED,
|
|
117
|
+
Watcher,
|
|
118
|
+
fileWatcher
|
|
119
|
+
};
|