@dbx-tools/path 0.9.119 → 0.9.121
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/README.md +10 -7
- package/index.ts +4 -1
- package/lib/index.d.ts +4 -1
- package/lib/index.js +4 -2
- package/lib/src/find.d.ts +8 -5
- package/lib/src/find.js +38 -12
- package/lib/src/git-ignore.d.ts +45 -0
- package/lib/src/git-ignore.js +161 -0
- package/lib/src/scan.d.ts +9 -3
- package/lib/src/scan.js +1 -1
- package/lib/src/watch.d.ts +2 -2
- package/lib/src/watch.js +75 -11
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +12 -3
- package/src/find.ts +55 -11
- package/src/git-ignore.ts +200 -0
- package/src/scan.ts +9 -3
- package/src/watch.ts +93 -13
package/lib/src/watch.js
CHANGED
|
@@ -8,26 +8,30 @@
|
|
|
8
8
|
*
|
|
9
9
|
* @module
|
|
10
10
|
*/
|
|
11
|
+
import { readFile } from "node:fs/promises";
|
|
11
12
|
import { isAbsolute, relative, resolve } from "path";
|
|
13
|
+
import { errorUtils, log } from "@dbx-tools/shared-core";
|
|
12
14
|
import { watch } from "chokidar";
|
|
13
15
|
import { hasMagic } from "glob";
|
|
14
16
|
import { findFiles } from "./find.js";
|
|
17
|
+
import { GitIgnore } from "./git-ignore.js";
|
|
15
18
|
import { ignorePathMatcher } from "./ignore.js";
|
|
16
19
|
import { pathMatchTests } from "./match.js";
|
|
17
20
|
import { FOLLOW_SYMLINKS_DEFAULT } from "./scan.js";
|
|
21
|
+
const logger = log.logger("path/watch");
|
|
18
22
|
/**
|
|
19
23
|
* Watches files and directories for real-time changes, applying the shared
|
|
20
24
|
* ignore groups so it prunes the same paths {@link findFiles} skips for the
|
|
21
25
|
* same patterns.
|
|
22
26
|
*/
|
|
23
|
-
export function watchFiles(paths, options) {
|
|
24
|
-
const normalized = toNormalizedFileWatchOptions(options);
|
|
25
|
-
const { ignored, cwd, followSymlinks, ...chokidarOptions } = normalized;
|
|
27
|
+
export async function watchFiles(paths, options) {
|
|
28
|
+
const normalized = await toNormalizedFileWatchOptions(options);
|
|
29
|
+
const { gitIgnore, ignored, cwd, followSymlinks, ...chokidarOptions } = normalized;
|
|
26
30
|
const { paths: literals, globs } = partitionPaths(paths);
|
|
27
31
|
let watchPaths;
|
|
28
32
|
if (globs.length > 0) {
|
|
29
33
|
const distinctWatchPaths = new Set(literals);
|
|
30
|
-
for (const path of findFiles(globs, toFindFilesOptions(normalized))) {
|
|
34
|
+
for await (const path of findFiles(globs, toFindFilesOptions(normalized))) {
|
|
31
35
|
distinctWatchPaths.add(path);
|
|
32
36
|
}
|
|
33
37
|
watchPaths = [...distinctWatchPaths];
|
|
@@ -35,12 +39,21 @@ export function watchFiles(paths, options) {
|
|
|
35
39
|
else {
|
|
36
40
|
watchPaths = literals;
|
|
37
41
|
}
|
|
38
|
-
|
|
42
|
+
const watcher = watch(watchPaths, {
|
|
39
43
|
...chokidarOptions,
|
|
40
44
|
cwd,
|
|
41
45
|
followSymlinks,
|
|
42
46
|
ignored,
|
|
43
47
|
});
|
|
48
|
+
if (gitIgnore) {
|
|
49
|
+
attachGitIgnoreWatcher(watcher, gitIgnore, watchPaths, {
|
|
50
|
+
cwd,
|
|
51
|
+
followSymlinks,
|
|
52
|
+
ignoreOptions: options?.ignoreOptions,
|
|
53
|
+
persistent: chokidarOptions.persistent,
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
return watcher;
|
|
44
57
|
}
|
|
45
58
|
function partitionPaths(paths) {
|
|
46
59
|
const globs = [];
|
|
@@ -55,13 +68,18 @@ function partitionPaths(paths) {
|
|
|
55
68
|
* built-in groups are consolidated into one chokidar {@link MatchFunction}. When
|
|
56
69
|
* `stats` marks a directory, the matcher also tests `path + "/"` for pruning.
|
|
57
70
|
*/
|
|
58
|
-
function toNormalizedFileWatchOptions(options) {
|
|
71
|
+
async function toNormalizedFileWatchOptions(options) {
|
|
59
72
|
const { cwd, ignore, followSymlinks, ignoreOptions, ...chokidarOptions } = options ?? {};
|
|
73
|
+
const root = cwd ?? process.cwd();
|
|
74
|
+
const gitIgnore = ignoreOptions?.git
|
|
75
|
+
? await GitIgnore.load(root, { ignoreOptions, followSymlinks })
|
|
76
|
+
: undefined;
|
|
60
77
|
return {
|
|
61
78
|
...chokidarOptions,
|
|
62
|
-
cwd:
|
|
79
|
+
cwd: root,
|
|
63
80
|
followSymlinks: followSymlinks ?? FOLLOW_SYMLINKS_DEFAULT,
|
|
64
|
-
|
|
81
|
+
...(gitIgnore ? { gitIgnore } : {}),
|
|
82
|
+
ignored: toWatchMatchFunction(ignore, ignoreOptions, root, gitIgnore),
|
|
65
83
|
};
|
|
66
84
|
}
|
|
67
85
|
/** Glob expansion reuses the normalized ignore matcher as a cwd-relative path predicate. */
|
|
@@ -78,7 +96,7 @@ function toFindFilesOptions(normalized) {
|
|
|
78
96
|
* {@link MatchFunction}s into one ignore test. Directory pruning uses `stats`
|
|
79
97
|
* when chokidar supplies it; glob expansion passes `undefined`.
|
|
80
98
|
*/
|
|
81
|
-
function toWatchMatchFunction(ignore, ignoreOptions, cwd) {
|
|
99
|
+
function toWatchMatchFunction(ignore, ignoreOptions, cwd, gitIgnore) {
|
|
82
100
|
const patterns = [];
|
|
83
101
|
const functions = [];
|
|
84
102
|
if (ignore !== undefined) {
|
|
@@ -94,6 +112,8 @@ function toWatchMatchFunction(ignore, ignoreOptions, cwd) {
|
|
|
94
112
|
matcher = matcher.or(...pathMatchTests(...patterns));
|
|
95
113
|
const matchPath = (path, stats) => {
|
|
96
114
|
const rel = toCwdRelativePath(path, cwd);
|
|
115
|
+
if (gitIgnore?.ignores(rel, stats?.isDirectory() ?? false))
|
|
116
|
+
return true;
|
|
97
117
|
if (matcher(rel))
|
|
98
118
|
return true;
|
|
99
119
|
for (const fn of functions) {
|
|
@@ -113,6 +133,50 @@ function toWatchMatchFunction(ignore, ignoreOptions, cwd) {
|
|
|
113
133
|
};
|
|
114
134
|
return matchPath;
|
|
115
135
|
}
|
|
136
|
+
function attachGitIgnoreWatcher(watcher, gitIgnore, watchPaths, options) {
|
|
137
|
+
const builtInIgnore = ignorePathMatcher(options.ignoreOptions);
|
|
138
|
+
const controls = watch(".", {
|
|
139
|
+
atomic: false,
|
|
140
|
+
cwd: options.cwd,
|
|
141
|
+
followSymlinks: options.followSymlinks,
|
|
142
|
+
ignoreInitial: true,
|
|
143
|
+
persistent: options.persistent,
|
|
144
|
+
ignored(path, stats) {
|
|
145
|
+
const relativePath = toCwdRelativePath(path, options.cwd);
|
|
146
|
+
if (GitIgnore.isFile(relativePath))
|
|
147
|
+
return false;
|
|
148
|
+
if (builtInIgnore(relativePath) || builtInIgnore(`${relativePath}/`))
|
|
149
|
+
return true;
|
|
150
|
+
return stats ? !stats.isDirectory() : false;
|
|
151
|
+
},
|
|
152
|
+
});
|
|
153
|
+
const reload = (path) => {
|
|
154
|
+
void readFile(resolve(options.cwd, path), "utf8")
|
|
155
|
+
.then((content) => {
|
|
156
|
+
gitIgnore.set(path, content);
|
|
157
|
+
watcher.add([...watchPaths]);
|
|
158
|
+
logger.debug(".gitignore updated", { path });
|
|
159
|
+
})
|
|
160
|
+
.catch((error) => {
|
|
161
|
+
logger.warn("failed to reload .gitignore", {
|
|
162
|
+
path,
|
|
163
|
+
error: errorUtils.toError(error),
|
|
164
|
+
});
|
|
165
|
+
});
|
|
166
|
+
};
|
|
167
|
+
controls.on("add", reload);
|
|
168
|
+
controls.on("change", reload);
|
|
169
|
+
controls.on("unlink", (path) => {
|
|
170
|
+
gitIgnore.delete(path);
|
|
171
|
+
watcher.add([...watchPaths]);
|
|
172
|
+
logger.debug(".gitignore removed", { path });
|
|
173
|
+
});
|
|
174
|
+
controls.on("error", (error) => watcher.emit("error", error));
|
|
175
|
+
const close = watcher.close.bind(watcher);
|
|
176
|
+
watcher.close = async () => {
|
|
177
|
+
await Promise.all([close(), controls.close()]);
|
|
178
|
+
};
|
|
179
|
+
}
|
|
116
180
|
/** Aligns chokidar paths with the cwd-relative form {@link findFiles} uses. */
|
|
117
181
|
function toCwdRelativePath(path, cwd) {
|
|
118
182
|
if (!isAbsolute(path))
|
|
@@ -126,7 +190,7 @@ if (import.meta.main) {
|
|
|
126
190
|
const cwd = resolve(process.argv[2] ?? resolve(import.meta.dirname, ".."));
|
|
127
191
|
console.log("--- Starting File Watcher ---");
|
|
128
192
|
console.log(`Working Directory: ${cwd}`);
|
|
129
|
-
const watcher = watchFiles("**/src/**", {
|
|
193
|
+
const watcher = await watchFiles("**/src/**", {
|
|
130
194
|
cwd,
|
|
131
195
|
ignoreInitial: false,
|
|
132
196
|
ignore: ["**/index.ts", "**/core/**"],
|
|
@@ -142,4 +206,4 @@ if (import.meta.main) {
|
|
|
142
206
|
});
|
|
143
207
|
console.log("Watcher started");
|
|
144
208
|
}
|
|
145
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2F0Y2guanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvd2F0Y2gudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7OztHQVNHO0FBR0gsT0FBTyxFQUFFLFVBQVUsRUFBRSxRQUFRLEVBQUUsT0FBTyxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQ3JELE9BQU8sRUFBa0MsS0FBSyxFQUFFLE1BQU0sVUFBVSxDQUFDO0FBQ2pFLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDaEMsT0FBTyxFQUFFLFNBQVMsRUFBd0IsTUFBTSxXQUFXLENBQUM7QUFDNUQsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sYUFBYSxDQUFDO0FBQ2hELE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSxZQUFZLENBQUM7QUFDNUMsT0FBTyxFQUEwQyx1QkFBdUIsRUFBRSxNQUFNLFdBQVcsQ0FBQztBQVk1Rjs7OztHQUlHO0FBQ0gsTUFBTSxVQUFVLFVBQVUsQ0FBQyxLQUF3QixFQUFFLE9BQTBCO0lBQzdFLE1BQU0sVUFBVSxHQUFHLDRCQUE0QixDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQ3pELE1BQU0sRUFBRSxPQUFPLEVBQUUsR0FBRyxFQUFFLGNBQWMsRUFBRSxHQUFHLGVBQWUsRUFBRSxHQUFHLFVBQVUsQ0FBQztJQUN4RSxNQUFNLEVBQUUsS0FBSyxFQUFFLFFBQVEsRUFBRSxLQUFLLEVBQUUsR0FBRyxjQUFjLENBQUMsS0FBSyxDQUFDLENBQUM7SUFFekQsSUFBSSxVQUFvQixDQUFDO0lBQ3pCLElBQUksS0FBSyxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUUsQ0FBQztRQUNyQixNQUFNLGtCQUFrQixHQUFHLElBQUksR0FBRyxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQzdDLEtBQUssTUFBTSxJQUFJLElBQUksU0FBUyxDQUFDLEtBQUssRUFBRSxrQkFBa0IsQ0FBQyxVQUFVLENBQUMsQ0FBQyxFQUFFLENBQUM7WUFDcEUs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QUFHLEdBQUcsT0FBTyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLElBQUksT0FBTyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFLElBQUksQ0FBQyxDQUFDLENBQUM7SUFDM0UsT0FBTyxDQUFDLEdBQUcsQ0FBQywrQkFBK0IsQ0FBQyxDQUFDO0lBQzdDLE9BQU8sQ0FBQyxHQUFHLENBQUMsc0JBQXNCLEdBQUcsRUFBRSxDQUFDLENBQUM7SUFFekMsTUFBTSxPQUFPLEdBQUcsVUFBVSxDQUFDLFdBQVcsRUFBRTtRQUN0QyxHQUFHO1FBQ0gsYUFBYSxFQUFFLEtBQUs7UUFDcEIsTUFBTSxFQUFFLENBQUMsYUFBYSxFQUFFLFlBQVksQ0FBQztRQUNyQyxhQUFhLEVBQUU7WUFDYixJQUFJLEVBQUUsS0FBSztTQUNaO0tBQ0YsQ0FBQyxDQUFDO0lBQ0gsT0FBTyxDQUFDLEVBQUUsQ0FBQyxLQUFLLEVBQUUsQ0FBQyxLQUFhLEVBQUUsSUFBWSxFQUFFLEVBQUU7UUFDaEQsT0FBTyxDQUFDLEdBQUcsQ0FBQyxJQUFJLEtBQUssQ0FBQyxXQUFXLEVBQUUsS0FBSyxJQUFJLEVBQUUsQ0FBQyxDQUFDO0lBQ2xELENBQUMsQ0FBQyxDQUFDO0lBQ0gsT0FBTyxDQUFDLEVBQUUsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxLQUFLLEVBQUUsRUFBRTtRQUM1QixPQUFPLENBQUMsS0FBSyxDQUFDLGdCQUFnQixFQUFFLEtBQUssQ0FBQyxDQUFDO0lBQ3pDLENBQUMsQ0FBQyxDQUFDO0lBQ0gsT0FBTyxDQUFDLEdBQUcsQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO0FBQ2pDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIFJlcG9zaXRvcnktY29uc2lzdGVudCBmaWxlIHdhdGNoaW5nIG92ZXIgQ2hva2lkYXIuXG4gKlxuICogUmV1c2UgYHdhdGNoRmlsZXMoKWAgd2hlbiBsaXZlIHdvcmtmbG93cyBtdXN0IG1hdGNoIGBmaW5kRmlsZXMoKWBcbiAqIGRpc2NvdmVyeSBhbmQgdGhlIGNlbnRyYWwgaWdub3JlIGNhdGFsb2d1ZS4gVGhlIHdyYXBwZXIgZXhwYW5kcyBnbG9icyBvbmNlLFxuICogcHJ1bmVzIGlnbm9yZWQgZGlyZWN0b3JpZXMgY29uc2lzdGVudGx5LCBhbmQgcHJlc2VydmVzIENob2tpZGFyJ3MgbmF0aXZlXG4gKiB3YXRjaGVyIHJlc3VsdCBmb3IgY2FsbGVycy5cbiAqXG4gKiBAbW9kdWxlXG4gKi9cblxuaW1wb3J0IHsgU3RhdHMgfSBmcm9tIFwiZnNcIjtcbmltcG9ydCB7IGlzQWJzb2x1dGUsIHJlbGF0aXZlLCByZXNvbHZlIH0gZnJvbSBcInBhdGhcIjtcbmltcG9ydCB7IENob2tpZGFyT3B0aW9ucywgTWF0Y2hGdW5jdGlvbiwgd2F0Y2ggfSBmcm9tIFwiY2hva2lkYXJcIjtcbmltcG9ydCB7IGhhc01hZ2ljIH0gZnJvbSBcImdsb2JcIjtcbmltcG9ydCB7IGZpbmRGaWxlcywgdHlwZSBGaWxlRmluZE9wdGlvbnMgfSBmcm9tIFwiLi9maW5kLnRzXCI7XG5pbXBvcnQgeyBpZ25vcmVQYXRoTWF0Y2hlciB9IGZyb20gXCIuL2lnbm9yZS50c1wiO1xuaW1wb3J0IHsgcGF0aE1hdGNoVGVzdHMgfSBmcm9tIFwiLi9tYXRjaC50c1wiO1xuaW1wb3J0IHsgRmlsZVNjYW5JZ25vcmVPcHRpb25zLCBGaWxlU2Nhbk9wdGlvbnMsIEZPTExPV19TWU1MSU5LU19ERUZBVUxUIH0gZnJvbSBcIi4vc2Nhbi50c1wiO1xuXG4vKiogQ2hva2lkYXIgb3B0aW9ucyBleHRlbmRlZCB3aXRoIHRoZSBzaGFyZWQgZGJ4LXRvb2xzIGlnbm9yZSBjb25maWd1cmF0aW9uLiAqL1xuZXhwb3J0IGludGVyZmFjZSBGaWxlV2F0Y2hPcHRpb25zXG4gIGV4dGVuZHMgT21pdDxDaG9raWRhck9wdGlvbnMsIFwiaWdub3JlZFwiPiwgT21pdDxGaWxlU2Nhbk9wdGlvbnMsIFwiaWdub3JlXCI+IHtcbiAgaWdub3JlPzogc3RyaW5nIHwgc3RyaW5nW10gfCBNYXRjaEZ1bmN0aW9uIHwgTWF0Y2hGdW5jdGlvbltdO1xufVxuXG5pbnRlcmZhY2UgTm9ybWFsaXplZEZpbGVXYXRjaE9wdGlvbnMgZXh0ZW5kcyBPbWl0PEZpbGVXYXRjaE9wdGlvbnMsIFwiaWdub3JlXCIgfCBcImlnbm9yZU9wdGlvbnNcIj4ge1xuICBpZ25vcmVkOiBNYXRjaEZ1bmN0aW9uO1xufVxuXG4vKipcbiAqIFdhdGNoZXMgZmlsZXMgYW5kIGRpcmVjdG9yaWVzIGZvciByZWFsLXRpbWUgY2hhbmdlcywgYXBwbHlpbmcgdGhlIHNoYXJlZFxuICogaWdub3JlIGdyb3VwcyBzbyBpdCBwcnVuZXMgdGhlIHNhbWUgcGF0aHMge0BsaW5rIGZpbmRGaWxlc30gc2tpcHMgZm9yIHRoZVxuICogc2FtZSBwYXR0ZXJucy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHdhdGNoRmlsZXMocGF0aHM6IHN0cmluZyB8IHN0cmluZ1tdLCBvcHRpb25zPzogRmlsZVdhdGNoT3B0aW9ucykge1xuICBjb25zdCBub3JtYWxpemVkID0gdG9Ob3JtYWxpemVkRmlsZVdhdGNoT3B0aW9ucyhvcHRpb25zKTtcbiAgY29uc3QgeyBpZ25vcmVkLCBjd2QsIGZvbGxvd1N5bWxpbmtzLCAuLi5jaG9raWRhck9wdGlvbnMgfSA9IG5vcm1hbGl6ZWQ7XG4gIGNvbnN0IHsgcGF0aHM6IGxpdGVyYWxzLCBnbG9icyB9ID0gcGFydGl0aW9uUGF0aHMocGF0aHMpO1xuXG4gIGxldCB3YXRjaFBhdGhzOiBzdHJpbmdbXTtcbiAgaWYgKGdsb2JzLmxlbmd0aCA+IDApIHtcbiAgICBjb25zdCBkaXN0aW5jdFdhdGNoUGF0aHMgPSBuZXcgU2V0KGxpdGVyYWxzKTtcbiAgICBmb3IgKGNvbnN0IHBhdGggb2YgZmluZEZpbGVzKGdsb2JzLCB0b0ZpbmRGaWxlc09wdGlvbnMobm9ybWFsaXplZCkpKSB7XG4gICAgICBkaXN0aW5jdFdhdGNoUGF0aHMuYWRkKHBhdGgpO1xuICAgIH1cbiAgICB3YXRjaFBhdGhzID0gWy4uLmRpc3RpbmN0V2F0Y2hQYXRoc107XG4gIH0gZWxzZSB7XG4gICAgd2F0Y2hQYXRocyA9IGxpdGVyYWxzO1xuICB9XG5cbiAgcmV0dXJuIHdhdGNoKHdhdGNoUGF0aHMsIHtcbiAgICAuLi5jaG9raWRhck9wdGlvbnMsXG4gICAgY3dkLFxuICAgIGZvbGxvd1N5bWxpbmtzLFxuICAgIGlnbm9yZWQsXG4gIH0pO1xufVxuXG5mdW5jdGlvbiBwYXJ0aXRpb25QYXRocyhwYXRoczogc3RyaW5nIHwgc3RyaW5nW10pOiB7IHBhdGhzOiBzdHJpbmdbXTsgZ2xvYnM6IHN0cmluZ1tdIH0ge1xuICBjb25zdCBnbG9iczogc3RyaW5nW10gPSBbXTtcbiAgY29uc3QgbGl0ZXJhbHM6IHN0cmluZ1tdID0gW107XG4gIGZvciAoY29uc3QgcGF0aCBvZiBBcnJheS5pc0FycmF5KHBhdGhzKSA/IHBhdGhzIDogW3BhdGhzXSkge1xuICAgIChoYXNNYWdpYyhwYXRoKSA/IGdsb2JzIDogbGl0ZXJhbHMpLnB1c2gocGF0aCk7XG4gIH1cbiAgcmV0dXJuIHsgcGF0aHM6IGxpdGVyYWxzLCBnbG9icyB9O1xufVxuXG4vKipcbiAqIEJ1aWxkcyB7QGxpbmsgTm9ybWFsaXplZEZpbGVXYXRjaE9wdGlvbnN9IGZpcnN0OiBhbGwgY2FsbGVyIGlnbm9yZSBpbnB1dHMgYW5kXG4gKiBidWlsdC1pbiBncm91cHMgYXJlIGNvbnNvbGlkYXRlZCBpbnRvIG9uZSBjaG9raWRhciB7QGxpbmsgTWF0Y2hGdW5jdGlvbn0uIFdoZW5cbiAqIGBzdGF0c2AgbWFya3MgYSBkaXJlY3RvcnksIHRoZSBtYXRjaGVyIGFsc28gdGVzdHMgYHBhdGggKyBcIi9cImAgZm9yIHBydW5pbmcuXG4gKi9cbmZ1bmN0aW9uIHRvTm9ybWFsaXplZEZpbGVXYXRjaE9wdGlvbnMob3B0aW9ucz86IEZpbGVXYXRjaE9wdGlvbnMpOiBOb3JtYWxpemVkRmlsZVdhdGNoT3B0aW9ucyAmIHtcbiAgY3dkOiBzdHJpbmc7XG4gIGZvbGxvd1N5bWxpbmtzOiBib29sZWFuO1xufSB7XG4gIGNvbnN0IHsgY3dkLCBpZ25vcmUsIGZvbGxvd1N5bWxpbmtzLCBpZ25vcmVPcHRpb25zLCAuLi5jaG9raWRhck9wdGlvbnMgfSA9IG9wdGlvbnMgPz8ge307XG4gIHJldHVybiB7XG4gICAgLi4uY2hva2lkYXJPcHRpb25zLFxuICAgIGN3ZDogY3dkID8/IHByb2Nlc3MuY3dkKCksXG4gICAgZm9sbG93U3ltbGlua3M6IGZvbGxvd1N5bWxpbmtzID8/IEZPTExPV19TWU1MSU5LU19ERUZBVUxULFxuICAgIGlnbm9yZWQ6IHRvV2F0Y2hNYXRjaEZ1bmN0aW9uKGlnbm9yZSwgaWdub3JlT3B0aW9ucywgY3dkID8/IHByb2Nlc3MuY3dkKCkpLFxuICB9O1xufVxuXG4vKiogR2xvYiBleHBhbnNpb24gcmV1c2VzIHRoZSBub3JtYWxpemVkIGlnbm9yZSBtYXRjaGVyIGFzIGEgY3dkLXJlbGF0aXZlIHBhdGggcHJlZGljYXRlLiAqL1xuZnVuY3Rpb24gdG9GaW5kRmlsZXNPcHRpb25zKFxuICBub3JtYWxpemVkOiBOb3JtYWxpemVkRmlsZVdhdGNoT3B0aW9ucyAmIHsgY3dkOiBzdHJpbmc7IGZvbGxvd1N5bWxpbmtzOiBib29sZWFuIH0sXG4pOiBGaWxlRmluZE9wdGlvbnMge1xuICBjb25zdCB7IGlnbm9yZWQsIGN3ZCwgZm9sbG93U3ltbGlua3MgfSA9IG5vcm1hbGl6ZWQ7XG4gIHJldHVybiB7XG4gICAgY3dkLFxuICAgIGZvbGxvd1N5bWxpbmtzLFxuICAgIGlnbm9yZTogKHBhdGgpID0+IGlnbm9yZWQocGF0aCwgdW5kZWZpbmVkKSxcbiAgfTtcbn1cblxuLyoqXG4gKiBDb25zb2xpZGF0ZXMgYnVpbHQtaW4gaWdub3JlIGdyb3VwcywgY2FsbGVyIGdsb2IgcGF0dGVybnMsIGFuZCBjYWxsZXJcbiAqIHtAbGluayBNYXRjaEZ1bmN0aW9ufXMgaW50byBvbmUgaWdub3JlIHRlc3QuIERpcmVjdG9yeSBwcnVuaW5nIHVzZXMgYHN0YXRzYFxuICogd2hlbiBjaG9raWRhciBzdXBwbGllcyBpdDsgZ2xvYiBleHBhbnNpb24gcGFzc2VzIGB1bmRlZmluZWRgLlxuICovXG5mdW5jdGlvbiB0b1dhdGNoTWF0Y2hGdW5jdGlvbihcbiAgaWdub3JlOiBGaWxlV2F0Y2hPcHRpb25zW1wiaWdub3JlXCJdIHwgdW5kZWZpbmVkLFxuICBpZ25vcmVPcHRpb25zOiBGaWxlU2Nhbklnbm9yZU9wdGlvbnMgfCB1bmRlZmluZWQsXG4gIGN3ZDogc3RyaW5nLFxuKTogTWF0Y2hGdW5jdGlvbiB7XG4gIGNvbnN0IHBhdHRlcm5zOiBzdHJpbmdbXSA9IFtdO1xuICBjb25zdCBmdW5jdGlvbnM6IE1hdGNoRnVuY3Rpb25bXSA9IFtdO1xuXG4gIGlmIChpZ25vcmUgIT09IHVuZGVmaW5lZCkge1xuICAgIGZvciAoY29uc3QgaXRlbSBvZiBBcnJheS5pc0FycmF5KGlnbm9yZSkgPyBpZ25vcmUgOiBbaWdub3JlXSkge1xuICAgICAgaWYgKHR5cGVvZiBpdGVtID09PSBcInN0cmluZ1wiKSBwYXR0ZXJucy5wdXNoKGl0ZW0pO1xuICAgICAgZWxzZSBmdW5jdGlvbnMucHVzaChpdGVtKTtcbiAgICB9XG4gIH1cblxuICBsZXQgbWF0Y2hlciA9IGlnbm9yZVBhdGhNYXRjaGVyKGlnbm9yZU9wdGlvbnMpO1xuICBpZiAocGF0dGVybnMubGVuZ3RoID4gMCkgbWF0Y2hlciA9IG1hdGNoZXIub3IoLi4ucGF0aE1hdGNoVGVzdHMoLi4ucGF0dGVybnMpKTtcblxuICBjb25zdCBtYXRjaFBhdGggPSAocGF0aDogc3RyaW5nLCBzdGF0cz86IFN0YXRzKTogYm9vbGVhbiA9PiB7XG4gICAgY29uc3QgcmVsID0gdG9Dd2RSZWxhdGl2ZVBhdGgocGF0aCwgY3dkKTtcbiAgICBpZiAobWF0Y2hlcihyZWwpKSByZXR1cm4gdHJ1ZTtcbiAgICBmb3IgKGNvbnN0IGZuIG9mIGZ1bmN0aW9ucykge1xuICAgICAgaWYgKGZuKHJlbCwgc3RhdHMpKSByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gICAgaWYgKHN0YXRzPy5pc0RpcmVjdG9yeSgpKSB7XG4gICAgICBjb25zdCBkaXJlY3RvcnlQYXRoID0gcmVsICsgXCIvXCI7XG4gICAgICBpZiAobWF0Y2hlcihkaXJlY3RvcnlQYXRoKSkgcmV0dXJuIHRydWU7XG4gICAgICBmb3IgKGNvbnN0IGZuIG9mIGZ1bmN0aW9ucykge1xuICAgICAgICBpZiAoZm4oZGlyZWN0b3J5UGF0aCwgc3RhdHMpKSByZXR1cm4gdHJ1ZTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9O1xuXG4gIHJldHVybiBtYXRjaFBhdGg7XG59XG5cbi8qKiBBbGlnbnMgY2hva2lkYXIgcGF0aHMgd2l0aCB0aGUgY3dkLXJlbGF0aXZlIGZvcm0ge0BsaW5rIGZpbmRGaWxlc30gdXNlcy4gKi9cbmZ1bmN0aW9uIHRvQ3dkUmVsYXRpdmVQYXRoKHBhdGg6IHN0cmluZywgY3dkOiBzdHJpbmcpOiBzdHJpbmcge1xuICBpZiAoIWlzQWJzb2x1dGUocGF0aCkpIHJldHVybiBwYXRoO1xuICBjb25zdCByZWwgPSByZWxhdGl2ZShjd2QsIHBhdGgpO1xuICByZXR1cm4gcmVsID09PSBcIlwiID8gXCIuXCIgOiByZWw7XG59XG5cbi8vIE1hbnVhbCBkZW1vOiBydW4gdGhpcyBmaWxlIGRpcmVjdGx5IChgYnVuIHNyYy93YXRjaC50cyBbZGlyXWApIHRvIHdhdGNoIGEgdHJlZVxuLy8gYW5kIGxvZyBldmVyeSBmaWxlIGV2ZW50IGFzIGl0IGhhcHBlbnMuIERlZmF1bHRzIHRvIHRoaXMgcGFja2FnZS5cbmlmIChpbXBvcnQubWV0YS5tYWluKSB7XG4gIGNvbnN0IGN3ZCA9IHJlc29sdmUocHJvY2Vzcy5hcmd2WzJdID8/IHJlc29sdmUoaW1wb3J0Lm1ldGEuZGlybmFtZSwgXCIuLlwiKSk7XG4gIGNvbnNvbGUubG9nKFwiLS0tIFN0YXJ0aW5nIEZpbGUgV2F0Y2hlciAtLS1cIik7XG4gIGNvbnNvbGUubG9nKGBXb3JraW5nIERpcmVjdG9yeTogJHtjd2R9YCk7XG5cbiAgY29uc3Qgd2F0Y2hlciA9IHdhdGNoRmlsZXMoXCIqKi9zcmMvKipcIiwge1xuICAgIGN3ZCxcbiAgICBpZ25vcmVJbml0aWFsOiBmYWxzZSxcbiAgICBpZ25vcmU6IFtcIioqL2luZGV4LnRzXCIsIFwiKiovY29yZS8qKlwiXSxcbiAgICBpZ25vcmVPcHRpb25zOiB7XG4gICAgICB0ZW1wOiBmYWxzZSxcbiAgICB9LFxuICB9KTtcbiAgd2F0Y2hlci5vbihcImFsbFwiLCAoZXZlbnQ6IHN0cmluZywgcGF0aDogc3RyaW5nKSA9PiB7XG4gICAgY29uc29sZS5sb2coYFske2V2ZW50LnRvVXBwZXJDYXNlKCl9XSAke3BhdGh9YCk7XG4gIH0pO1xuICB3YXRjaGVyLm9uKFwiZXJyb3JcIiwgKGVycm9yKSA9PiB7XG4gICAgY29uc29sZS5lcnJvcihcIldhdGNoZXIgZXJyb3I6XCIsIGVycm9yKTtcbiAgfSk7XG4gIGNvbnNvbGUubG9nKFwiV2F0Y2hlciBzdGFydGVkXCIpO1xufVxuIl19
|
|
209
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2F0Y2guanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvd2F0Y2gudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7OztHQVNHO0FBR0gsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBQzVDLE9BQU8sRUFBRSxVQUFVLEVBQUUsUUFBUSxFQUFFLE9BQU8sRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUNyRCxPQUFPLEVBQUUsVUFBVSxFQUFFLEdBQUcsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQ3pELE9BQU8sRUFBa0MsS0FBSyxFQUFrQixNQUFNLFVBQVUsQ0FBQztBQUNqRixPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQ2hDLE9BQU8sRUFBRSxTQUFTLEVBQXdCLE1BQU0sV0FBVyxDQUFDO0FBQzVELE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUM1QyxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFDaEQsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLFlBQVksQ0FBQztBQUM1QyxPQUFPLEVBQTBDLHVCQUF1QixFQUFFLE1BQU0sV0FBVyxDQUFDO0FBRTVGLE1BQU0sTUFBTSxHQUFHLEdBQUcsQ0FBQyxNQUFNLENBQUMsWUFBWSxDQUFDLENBQUM7QUFheEM7Ozs7R0FJRztBQUNILE1BQU0sQ0FBQyxLQUFLLFVBQVUsVUFBVSxDQUM5QixLQUF3QixFQUN4QixPQUEwQjtJQUUxQixNQUFNLFVBQVUsR0FBRyxNQUFNLDRCQUE0QixDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQy9ELE1BQU0sRUFBRSxTQUFTLEVBQUUsT0FBTyxFQUFFLEdBQUcsRUFBRSxjQUFjLEVBQUUsR0FBRyxlQUFlLEVBQUUsR0FBRyxVQUFVLENBQUM7SUFDbkYsTUFBTSxFQUFFLEtBQUssRUFBRSxRQUFRLEVBQUUsS0FBSyxFQUFFLEdBQUcsY0FBYyxDQUFDLEtB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LElBQUksQ0FBQyxPQUFPLEVBQUUsSUFBSSxDQUFDLENBQUMsQ0FBQztJQUMzRSxPQUFPLENBQUMsR0FBRyxDQUFDLCtCQUErQixDQUFDLENBQUM7SUFDN0MsT0FBTyxDQUFDLEdBQUcsQ0FBQyxzQkFBc0IsR0FBRyxFQUFFLENBQUMsQ0FBQztJQUV6QyxNQUFNLE9BQU8sR0FBRyxNQUFNLFVBQVUsQ0FBQyxXQUFXLEVBQUU7UUFDNUMsR0FBRztRQUNILGFBQWEsRUFBRSxLQUFLO1FBQ3BCLE1BQU0sRUFBRSxDQUFDLGFBQWEsRUFBRSxZQUFZLENBQUM7UUFDckMsYUFBYSxFQUFFO1lBQ2IsSUFBSSxFQUFFLEtBQUs7U0FDWjtLQUNGLENBQUMsQ0FBQztJQUNILE9BQU8sQ0FBQyxFQUFFLENBQUMsS0FBSyxFQUFFLENBQUMsS0FBYSxFQUFFLElBQVksRUFBRSxFQUFFO1FBQ2hELE9BQU8sQ0FBQyxHQUFHLENBQUMsSUFBSSxLQUFLLENBQUMsV0FBVyxFQUFFLEtBQUssSUFBSSxFQUFFLENBQUMsQ0FBQztJQUNsRCxDQUFDLENBQUMsQ0FBQztJQUNILE9BQU8sQ0FBQyxFQUFFLENBQUMsT0FBTyxFQUFFLENBQUMsS0FBSyxFQUFFLEVBQUU7UUFDNUIsT0FBTyxDQUFDLEtBQUssQ0FBQyxnQkFBZ0IsRUFBRSxLQUFLLENBQUMsQ0FBQztJQUN6QyxDQUFDLENBQUMsQ0FBQztJQUNILE9BQU8sQ0FBQyxHQUFHLENBQUMsaUJBQWlCLENBQUMsQ0FBQztBQUNqQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBSZXBvc2l0b3J5LWNvbnNpc3RlbnQgZmlsZSB3YXRjaGluZyBvdmVyIENob2tpZGFyLlxuICpcbiAqIFJldXNlIGB3YXRjaEZpbGVzKClgIHdoZW4gbGl2ZSB3b3JrZmxvd3MgbXVzdCBtYXRjaCBgZmluZEZpbGVzKClgXG4gKiBkaXNjb3ZlcnkgYW5kIHRoZSBjZW50cmFsIGlnbm9yZSBjYXRhbG9ndWUuIFRoZSB3cmFwcGVyIGV4cGFuZHMgZ2xvYnMgb25jZSxcbiAqIHBydW5lcyBpZ25vcmVkIGRpcmVjdG9yaWVzIGNvbnNpc3RlbnRseSwgYW5kIHByZXNlcnZlcyBDaG9raWRhcidzIG5hdGl2ZVxuICogd2F0Y2hlciByZXN1bHQgZm9yIGNhbGxlcnMuXG4gKlxuICogQG1vZHVsZVxuICovXG5cbmltcG9ydCB7IFN0YXRzIH0gZnJvbSBcImZzXCI7XG5pbXBvcnQgeyByZWFkRmlsZSB9IGZyb20gXCJub2RlOmZzL3Byb21pc2VzXCI7XG5pbXBvcnQgeyBpc0Fic29sdXRlLCByZWxhdGl2ZSwgcmVzb2x2ZSB9IGZyb20gXCJwYXRoXCI7XG5pbXBvcnQgeyBlcnJvclV0aWxzLCBsb2cgfSBmcm9tIFwiQGRieC10b29scy9zaGFyZWQtY29yZVwiO1xuaW1wb3J0IHsgQ2hva2lkYXJPcHRpb25zLCBNYXRjaEZ1bmN0aW9uLCB3YXRjaCwgdHlwZSBGU1dhdGNoZXIgfSBmcm9tIFwiY2hva2lkYXJcIjtcbmltcG9ydCB7IGhhc01hZ2ljIH0gZnJvbSBcImdsb2JcIjtcbmltcG9ydCB7IGZpbmRGaWxlcywgdHlwZSBGaWxlRmluZE9wdGlvbnMgfSBmcm9tIFwiLi9maW5kLnRzXCI7XG5pbXBvcnQgeyBHaXRJZ25vcmUgfSBmcm9tIFwiLi9naXQtaWdub3JlLnRzXCI7XG5pbXBvcnQgeyBpZ25vcmVQYXRoTWF0Y2hlciB9IGZyb20gXCIuL2lnbm9yZS50c1wiO1xuaW1wb3J0IHsgcGF0aE1hdGNoVGVzdHMgfSBmcm9tIFwiLi9tYXRjaC50c1wiO1xuaW1wb3J0IHsgRmlsZVNjYW5JZ25vcmVPcHRpb25zLCBGaWxlU2Nhbk9wdGlvbnMsIEZPTExPV19TWU1MSU5LU19ERUZBVUxUIH0gZnJvbSBcIi4vc2Nhbi50c1wiO1xuXG5jb25zdCBsb2dnZXIgPSBsb2cubG9nZ2VyKFwicGF0aC93YXRjaFwiKTtcblxuLyoqIENob2tpZGFyIG9wdGlvbnMgZXh0ZW5kZWQgd2l0aCB0aGUgc2hhcmVkIGRieC10b29scyBpZ25vcmUgY29uZmlndXJhdGlvbi4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgRmlsZVdhdGNoT3B0aW9uc1xuICBleHRlbmRzIE9taXQ8Q2hva2lkYXJPcHRpb25zLCBcImlnbm9yZWRcIj4sIE9taXQ8RmlsZVNjYW5PcHRpb25zLCBcImlnbm9yZVwiPiB7XG4gIGlnbm9yZT86IHN0cmluZyB8IHN0cmluZ1tdIHwgTWF0Y2hGdW5jdGlvbiB8IE1hdGNoRnVuY3Rpb25bXTtcbn1cblxuaW50ZXJmYWNlIE5vcm1hbGl6ZWRGaWxlV2F0Y2hPcHRpb25zIGV4dGVuZHMgT21pdDxGaWxlV2F0Y2hPcHRpb25zLCBcImlnbm9yZVwiIHwgXCJpZ25vcmVPcHRpb25zXCI+IHtcbiAgZ2l0SWdub3JlPzogR2l0SWdub3JlO1xuICBpZ25vcmVkOiBNYXRjaEZ1bmN0aW9uO1xufVxuXG4vKipcbiAqIFdhdGNoZXMgZmlsZXMgYW5kIGRpcmVjdG9yaWVzIGZvciByZWFsLXRpbWUgY2hhbmdlcywgYXBwbHlpbmcgdGhlIHNoYXJlZFxuICogaWdub3JlIGdyb3VwcyBzbyBpdCBwcnVuZXMgdGhlIHNhbWUgcGF0aHMge0BsaW5rIGZpbmRGaWxlc30gc2tpcHMgZm9yIHRoZVxuICogc2FtZSBwYXR0ZXJucy5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHdhdGNoRmlsZXMoXG4gIHBhdGhzOiBzdHJpbmcgfCBzdHJpbmdbXSxcbiAgb3B0aW9ucz86IEZpbGVXYXRjaE9wdGlvbnMsXG4pOiBQcm9taXNlPEZTV2F0Y2hlcj4ge1xuICBjb25zdCBub3JtYWxpemVkID0gYXdhaXQgdG9Ob3JtYWxpemVkRmlsZVdhdGNoT3B0aW9ucyhvcHRpb25zKTtcbiAgY29uc3QgeyBnaXRJZ25vcmUsIGlnbm9yZWQsIGN3ZCwgZm9sbG93U3ltbGlua3MsIC4uLmNob2tpZGFyT3B0aW9ucyB9ID0gbm9ybWFsaXplZDtcbiAgY29uc3QgeyBwYXRoczogbGl0ZXJhbHMsIGdsb2JzIH0gPSBwYXJ0aXRpb25QYXRocyhwYXRocyk7XG5cbiAgbGV0IHdhdGNoUGF0aHM6IHN0cmluZ1tdO1xuICBpZiAoZ2xvYnMubGVuZ3RoID4gMCkge1xuICAgIGNvbnN0IGRpc3RpbmN0V2F0Y2hQYXRocyA9IG5ldyBTZXQobGl0ZXJhbHMpO1xuICAgIGZvciBhd2FpdCAoY29uc3QgcGF0aCBvZiBmaW5kRmlsZXMoZ2xvYnMsIHRvRmluZEZpbGVzT3B0aW9ucyhub3JtYWxpemVkKSkpIHtcbiAgICAgIGRpc3RpbmN0V2F0Y2hQYXRocy5hZGQocGF0aCk7XG4gICAgfVxuICAgIHdhdGNoUGF0aHMgPSBbLi4uZGlzdGluY3RXYXRjaFBhdGhzXTtcbiAgfSBlbHNlIHtcbiAgICB3YXRjaFBhdGhzID0gbGl0ZXJhbHM7XG4gIH1cblxuICBjb25zdCB3YXRjaGVyID0gd2F0Y2god2F0Y2hQYXRocywge1xuICAgIC4uLmNob2tpZGFyT3B0aW9ucyxcbiAgICBjd2QsXG4gICAgZm9sbG93U3ltbGlua3MsXG4gICAgaWdub3JlZCxcbiAgfSk7XG4gIGlmIChnaXRJZ25vcmUpIHtcbiAgICBhdHRhY2hHaXRJZ25vcmVXYXRjaGVyKHdhdGNoZXIsIGdpdElnbm9yZSwgd2F0Y2hQYXRocywge1xuICAgICAgY3dkLFxuICAgICAgZm9sbG93U3ltbGlua3MsXG4gICAgICBpZ25vcmVPcHRpb25zOiBvcHRpb25zPy5pZ25vcmVPcHRpb25zLFxuICAgICAgcGVyc2lzdGVudDogY2hva2lkYXJPcHRpb25zLnBlcnNpc3RlbnQsXG4gICAgfSk7XG4gIH1cbiAgcmV0dXJuIHdhdGNoZXI7XG59XG5cbmZ1bmN0aW9uIHBhcnRpdGlvblBhdGhzKHBhdGhzOiBzdHJpbmcgfCBzdHJpbmdbXSk6IHsgcGF0aHM6IHN0cmluZ1tdOyBnbG9iczogc3RyaW5nW10gfSB7XG4gIGNvbnN0IGdsb2JzOiBzdHJpbmdbXSA9IFtdO1xuICBjb25zdCBsaXRlcmFsczogc3RyaW5nW10gPSBbXTtcbiAgZm9yIChjb25zdCBwYXRoIG9mIEFycmF5LmlzQXJyYXkocGF0aHMpID8gcGF0aHMgOiBbcGF0aHNdKSB7XG4gICAgKGhhc01hZ2ljKHBhdGgpID8gZ2xvYnMgOiBsaXRlcmFscykucHVzaChwYXRoKTtcbiAgfVxuICByZXR1cm4geyBwYXRoczogbGl0ZXJhbHMsIGdsb2JzIH07XG59XG5cbi8qKlxuICogQnVpbGRzIHtAbGluayBOb3JtYWxpemVkRmlsZVdhdGNoT3B0aW9uc30gZmlyc3Q6IGFsbCBjYWxsZXIgaWdub3JlIGlucHV0cyBhbmRcbiAqIGJ1aWx0LWluIGdyb3VwcyBhcmUgY29uc29saWRhdGVkIGludG8gb25lIGNob2tpZGFyIHtAbGluayBNYXRjaEZ1bmN0aW9ufS4gV2hlblxuICogYHN0YXRzYCBtYXJrcyBhIGRpcmVjdG9yeSwgdGhlIG1hdGNoZXIgYWxzbyB0ZXN0cyBgcGF0aCArIFwiL1wiYCBmb3IgcHJ1bmluZy5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gdG9Ob3JtYWxpemVkRmlsZVdhdGNoT3B0aW9ucyhvcHRpb25zPzogRmlsZVdhdGNoT3B0aW9ucyk6IFByb21pc2U8XG4gIE5vcm1hbGl6ZWRGaWxlV2F0Y2hPcHRpb25zICYge1xuICAgIGN3ZDogc3RyaW5nO1xuICAgIGZvbGxvd1N5bWxpbmtzOiBib29sZWFuO1xuICB9XG4+IHtcbiAgY29uc3QgeyBjd2QsIGlnbm9yZSwgZm9sbG93U3ltbGlua3MsIGlnbm9yZU9wdGlvbnMsIC4uLmNob2tpZGFyT3B0aW9ucyB9ID0gb3B0aW9ucyA/PyB7fTtcbiAgY29uc3Qgcm9vdCA9IGN3ZCA/PyBwcm9jZXNzLmN3ZCgpO1xuICBjb25zdCBnaXRJZ25vcmUgPSBpZ25vcmVPcHRpb25zPy5naXRcbiAgICA/IGF3YWl0IEdpdElnbm9yZS5sb2FkKHJvb3QsIHsgaWdub3JlT3B0aW9ucywgZm9sbG93U3ltbGlua3MgfSlcbiAgICA6IHVuZGVmaW5lZDtcbiAgcmV0dXJuIHtcbiAgICAuLi5jaG9raWRhck9wdGlvbnMsXG4gICAgY3dkOiByb290LFxuICAgIGZvbGxvd1N5bWxpbmtzOiBmb2xsb3dTeW1saW5rcyA/PyBGT0xMT1dfU1lNTElOS1NfREVGQVVMVCxcbiAgICAuLi4oZ2l0SWdub3JlID8geyBnaXRJZ25vcmUgfSA6IHt9KSxcbiAgICBpZ25vcmVkOiB0b1dhdGNoTWF0Y2hGdW5jdGlvbihpZ25vcmUsIGlnbm9yZU9wdGlvbnMsIHJvb3QsIGdpdElnbm9yZSksXG4gIH07XG59XG5cbi8qKiBHbG9iIGV4cGFuc2lvbiByZXVzZXMgdGhlIG5vcm1hbGl6ZWQgaWdub3JlIG1hdGNoZXIgYXMgYSBjd2QtcmVsYXRpdmUgcGF0aCBwcmVkaWNhdGUuICovXG5mdW5jdGlvbiB0b0ZpbmRGaWxlc09wdGlvbnMoXG4gIG5vcm1hbGl6ZWQ6IE5vcm1hbGl6ZWRGaWxlV2F0Y2hPcHRpb25zICYgeyBjd2Q6IHN0cmluZzsgZm9sbG93U3ltbGlua3M6IGJvb2xlYW4gfSxcbik6IEZpbGVGaW5kT3B0aW9ucyB7XG4gIGNvbnN0IHsgaWdub3JlZCwgY3dkLCBmb2xsb3dTeW1saW5rcyB9ID0gbm9ybWFsaXplZDtcbiAgcmV0dXJuIHtcbiAgICBjd2QsXG4gICAgZm9sbG93U3ltbGlua3MsXG4gICAgaWdub3JlOiAocGF0aCkgPT4gaWdub3JlZChwYXRoLCB1bmRlZmluZWQpLFxuICB9O1xufVxuXG4vKipcbiAqIENvbnNvbGlkYXRlcyBidWlsdC1pbiBpZ25vcmUgZ3JvdXBzLCBjYWxsZXIgZ2xvYiBwYXR0ZXJucywgYW5kIGNhbGxlclxuICoge0BsaW5rIE1hdGNoRnVuY3Rpb259cyBpbnRvIG9uZSBpZ25vcmUgdGVzdC4gRGlyZWN0b3J5IHBydW5pbmcgdXNlcyBgc3RhdHNgXG4gKiB3aGVuIGNob2tpZGFyIHN1cHBsaWVzIGl0OyBnbG9iIGV4cGFuc2lvbiBwYXNzZXMgYHVuZGVmaW5lZGAuXG4gKi9cbmZ1bmN0aW9uIHRvV2F0Y2hNYXRjaEZ1bmN0aW9uKFxuICBpZ25vcmU6IEZpbGVXYXRjaE9wdGlvbnNbXCJpZ25vcmVcIl0gfCB1bmRlZmluZWQsXG4gIGlnbm9yZU9wdGlvbnM6IEZpbGVTY2FuSWdub3JlT3B0aW9ucyB8IHVuZGVmaW5lZCxcbiAgY3dkOiBzdHJpbmcsXG4gIGdpdElnbm9yZT86IEdpdElnbm9yZSxcbik6IE1hdGNoRnVuY3Rpb24ge1xuICBjb25zdCBwYXR0ZXJuczogc3RyaW5nW10gPSBbXTtcbiAgY29uc3QgZnVuY3Rpb25zOiBNYXRjaEZ1bmN0aW9uW10gPSBbXTtcblxuICBpZiAoaWdub3JlICE9PSB1bmRlZmluZWQpIHtcbiAgICBmb3IgKGNvbnN0IGl0ZW0gb2YgQXJyYXkuaXNBcnJheShpZ25vcmUpID8gaWdub3JlIDogW2lnbm9yZV0pIHtcbiAgICAgIGlmICh0eXBlb2YgaXRlbSA9PT0gXCJzdHJpbmdcIikgcGF0dGVybnMucHVzaChpdGVtKTtcbiAgICAgIGVsc2UgZnVuY3Rpb25zLnB1c2goaXRlbSk7XG4gICAgfVxuICB9XG5cbiAgbGV0IG1hdGNoZXIgPSBpZ25vcmVQYXRoTWF0Y2hlcihpZ25vcmVPcHRpb25zKTtcbiAgaWYgKHBhdHRlcm5zLmxlbmd0aCA+IDApIG1hdGNoZXIgPSBtYXRjaGVyLm9yKC4uLnBhdGhNYXRjaFRlc3RzKC4uLnBhdHRlcm5zKSk7XG5cbiAgY29uc3QgbWF0Y2hQYXRoID0gKHBhdGg6IHN0cmluZywgc3RhdHM/OiBTdGF0cyk6IGJvb2xlYW4gPT4ge1xuICAgIGNvbnN0IHJlbCA9IHRvQ3dkUmVsYXRpdmVQYXRoKHBhdGgsIGN3ZCk7XG4gICAgaWYgKGdpdElnbm9yZT8uaWdub3JlcyhyZWwsIHN0YXRzPy5pc0RpcmVjdG9yeSgpID8/IGZhbHNlKSkgcmV0dXJuIHRydWU7XG4gICAgaWYgKG1hdGNoZXIocmVsKSkgcmV0dXJuIHRydWU7XG4gICAgZm9yIChjb25zdCBmbiBvZiBmdW5jdGlvbnMpIHtcbiAgICAgIGlmIChmbihyZWwsIHN0YXRzKSkgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIGlmIChzdGF0cz8uaXNEaXJlY3RvcnkoKSkge1xuICAgICAgY29uc3QgZGlyZWN0b3J5UGF0aCA9IHJlbCArIFwiL1wiO1xuICAgICAgaWYgKG1hdGNoZXIoZGlyZWN0b3J5UGF0aCkpIHJldHVybiB0cnVlO1xuICAgICAgZm9yIChjb25zdCBmbiBvZiBmdW5jdGlvbnMpIHtcbiAgICAgICAgaWYgKGZuKGRpcmVjdG9yeVBhdGgsIHN0YXRzKSkgcmV0dXJuIHRydWU7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcblxuICByZXR1cm4gbWF0Y2hQYXRoO1xufVxuXG5mdW5jdGlvbiBhdHRhY2hHaXRJZ25vcmVXYXRjaGVyKFxuICB3YXRjaGVyOiBGU1dhdGNoZXIsXG4gIGdpdElnbm9yZTogR2l0SWdub3JlLFxuICB3YXRjaFBhdGhzOiByZWFkb25seSBzdHJpbmdbXSxcbiAgb3B0aW9uczoge1xuICAgIGN3ZDogc3RyaW5nO1xuICAgIGZvbGxvd1N5bWxpbmtzOiBib29sZWFuO1xuICAgIGlnbm9yZU9wdGlvbnM/OiBGaWxlU2Nhbklnbm9yZU9wdGlvbnM7XG4gICAgcGVyc2lzdGVudD86IGJvb2xlYW47XG4gIH0sXG4pOiB2b2lkIHtcbiAgY29uc3QgYnVpbHRJbklnbm9yZSA9IGlnbm9yZVBhdGhNYXRjaGVyKG9wdGlvbnMuaWdub3JlT3B0aW9ucyk7XG4gIGNvbnN0IGNvbnRyb2xzID0gd2F0Y2goXCIuXCIsIHtcbiAgICBhdG9taWM6IGZhbHNlLFxuICAgIGN3ZDogb3B0aW9ucy5jd2QsXG4gICAgZm9sbG93U3ltbGlua3M6IG9wdGlvbnMuZm9sbG93U3ltbGlua3MsXG4gICAgaWdub3JlSW5pdGlhbDogdHJ1ZSxcbiAgICBwZXJzaXN0ZW50OiBvcHRpb25zLnBlcnNpc3RlbnQsXG4gICAgaWdub3JlZChwYXRoLCBzdGF0cykge1xuICAgICAgY29uc3QgcmVsYXRpdmVQYXRoID0gdG9Dd2RSZWxhdGl2ZVBhdGgocGF0aCwgb3B0aW9ucy5jd2QpO1xuICAgICAgaWYgKEdpdElnbm9yZS5pc0ZpbGUocmVsYXRpdmVQYXRoKSkgcmV0dXJuIGZhbHNlO1xuICAgICAgaWYgKGJ1aWx0SW5JZ25vcmUocmVsYXRpdmVQYXRoKSB8fCBidWlsdEluSWdub3JlKGAke3JlbGF0aXZlUGF0aH0vYCkpIHJldHVybiB0cnVlO1xuICAgICAgcmV0dXJuIHN0YXRzID8gIXN0YXRzLmlzRGlyZWN0b3J5KCkgOiBmYWxzZTtcbiAgICB9LFxuICB9KTtcbiAgY29uc3QgcmVsb2FkID0gKHBhdGg6IHN0cmluZyk6IHZvaWQgPT4ge1xuICAgIHZvaWQgcmVhZEZpbGUocmVzb2x2ZShvcHRpb25zLmN3ZCwgcGF0aCksIFwidXRmOFwiKVxuICAgICAgLnRoZW4oKGNvbnRlbnQpID0+IHtcbiAgICAgICAgZ2l0SWdub3JlLnNldChwYXRoLCBjb250ZW50KTtcbiAgICAgICAgd2F0Y2hlci5hZGQoWy4uLndhdGNoUGF0aHNdKTtcbiAgICAgICAgbG9nZ2VyLmRlYnVnKFwiLmdpdGlnbm9yZSB1cGRhdGVkXCIsIHsgcGF0aCB9KTtcbiAgICAgIH0pXG4gICAgICAuY2F0Y2goKGVycm9yKSA9PiB7XG4gICAgICAgIGxvZ2dlci53YXJuKFwiZmFpbGVkIHRvIHJlbG9hZCAuZ2l0aWdub3JlXCIsIHtcbiAgICAgICAgICBwYXRoLFxuICAgICAgICAgIGVycm9yOiBlcnJvclV0aWxzLnRvRXJyb3IoZXJyb3IpLFxuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICB9O1xuICBjb250cm9scy5vbihcImFkZFwiLCByZWxvYWQpO1xuICBjb250cm9scy5vbihcImNoYW5nZVwiLCByZWxvYWQpO1xuICBjb250cm9scy5vbihcInVubGlua1wiLCAocGF0aCkgPT4ge1xuICAgIGdpdElnbm9yZS5kZWxldGUocGF0aCk7XG4gICAgd2F0Y2hlci5hZGQoWy4uLndhdGNoUGF0aHNdKTtcbiAgICBsb2dnZXIuZGVidWcoXCIuZ2l0aWdub3JlIHJlbW92ZWRcIiwgeyBwYXRoIH0pO1xuICB9KTtcbiAgY29udHJvbHMub24oXCJlcnJvclwiLCAoZXJyb3IpID0+IHdhdGNoZXIuZW1pdChcImVycm9yXCIsIGVycm9yKSk7XG4gIGNvbnN0IGNsb3NlID0gd2F0Y2hlci5jbG9zZS5iaW5kKHdhdGNoZXIpO1xuICB3YXRjaGVyLmNsb3NlID0gYXN5bmMgKCkgPT4ge1xuICAgIGF3YWl0IFByb21pc2UuYWxsKFtjbG9zZSgpLCBjb250cm9scy5jbG9zZSgpXSk7XG4gIH07XG59XG5cbi8qKiBBbGlnbnMgY2hva2lkYXIgcGF0aHMgd2l0aCB0aGUgY3dkLXJlbGF0aXZlIGZvcm0ge0BsaW5rIGZpbmRGaWxlc30gdXNlcy4gKi9cbmZ1bmN0aW9uIHRvQ3dkUmVsYXRpdmVQYXRoKHBhdGg6IHN0cmluZywgY3dkOiBzdHJpbmcpOiBzdHJpbmcge1xuICBpZiAoIWlzQWJzb2x1dGUocGF0aCkpIHJldHVybiBwYXRoO1xuICBjb25zdCByZWwgPSByZWxhdGl2ZShjd2QsIHBhdGgpO1xuICByZXR1cm4gcmVsID09PSBcIlwiID8gXCIuXCIgOiByZWw7XG59XG5cbi8vIE1hbnVhbCBkZW1vOiBydW4gdGhpcyBmaWxlIGRpcmVjdGx5IChgYnVuIHNyYy93YXRjaC50cyBbZGlyXWApIHRvIHdhdGNoIGEgdHJlZVxuLy8gYW5kIGxvZyBldmVyeSBmaWxlIGV2ZW50IGFzIGl0IGhhcHBlbnMuIERlZmF1bHRzIHRvIHRoaXMgcGFja2FnZS5cbmlmIChpbXBvcnQubWV0YS5tYWluKSB7XG4gIGNvbnN0IGN3ZCA9IHJlc29sdmUocHJvY2Vzcy5hcmd2WzJdID8/IHJlc29sdmUoaW1wb3J0Lm1ldGEuZGlybmFtZSwgXCIuLlwiKSk7XG4gIGNvbnNvbGUubG9nKFwiLS0tIFN0YXJ0aW5nIEZpbGUgV2F0Y2hlciAtLS1cIik7XG4gIGNvbnNvbGUubG9nKGBXb3JraW5nIERpcmVjdG9yeTogJHtjd2R9YCk7XG5cbiAgY29uc3Qgd2F0Y2hlciA9IGF3YWl0IHdhdGNoRmlsZXMoXCIqKi9zcmMvKipcIiwge1xuICAgIGN3ZCxcbiAgICBpZ25vcmVJbml0aWFsOiBmYWxzZSxcbiAgICBpZ25vcmU6IFtcIioqL2luZGV4LnRzXCIsIFwiKiovY29yZS8qKlwiXSxcbiAgICBpZ25vcmVPcHRpb25zOiB7XG4gICAgICB0ZW1wOiBmYWxzZSxcbiAgICB9LFxuICB9KTtcbiAgd2F0Y2hlci5vbihcImFsbFwiLCAoZXZlbnQ6IHN0cmluZywgcGF0aDogc3RyaW5nKSA9PiB7XG4gICAgY29uc29sZS5sb2coYFske2V2ZW50LnRvVXBwZXJDYXNlKCl9XSAke3BhdGh9YCk7XG4gIH0pO1xuICB3YXRjaGVyLm9uKFwiZXJyb3JcIiwgKGVycm9yKSA9PiB7XG4gICAgY29uc29sZS5lcnJvcihcIldhdGNoZXIgZXJyb3I6XCIsIGVycm9yKTtcbiAgfSk7XG4gIGNvbnNvbGUubG9nKFwiV2F0Y2hlciBzdGFydGVkXCIpO1xufVxuIl19
|
package/lib/tsconfig.tsbuildinfo
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"root":["../src/find.ts","../src/ignore.ts","../src/match.ts","../src/pattern.ts","../src/scan.ts","../src/watch.ts","../index.ts"],"version":"5.9.3"}
|
|
1
|
+
{"root":["../src/find.ts","../src/git-ignore.ts","../src/ignore.ts","../src/match.ts","../src/pattern.ts","../src/scan.ts","../src/watch.ts","../index.ts"],"version":"5.9.3"}
|
package/package.json
CHANGED
|
@@ -23,10 +23,11 @@
|
|
|
23
23
|
"typescript": "^5.9.3"
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"@dbx-tools/core": "^0.9.
|
|
27
|
-
"@dbx-tools/shared-core": "^0.9.
|
|
26
|
+
"@dbx-tools/core": "^0.9.121",
|
|
27
|
+
"@dbx-tools/shared-core": "^0.9.121",
|
|
28
28
|
"chokidar": "^4.0.3",
|
|
29
29
|
"glob": "^13.0.6",
|
|
30
|
+
"ignore": "^7.0.12",
|
|
30
31
|
"minimatch": "^10.2.5"
|
|
31
32
|
},
|
|
32
33
|
"main": "./lib/index.js",
|
|
@@ -44,6 +45,10 @@
|
|
|
44
45
|
"types": "./lib/src/find.d.ts",
|
|
45
46
|
"default": "./lib/src/find.js"
|
|
46
47
|
},
|
|
48
|
+
"./git-ignore": {
|
|
49
|
+
"types": "./lib/src/git-ignore.d.ts",
|
|
50
|
+
"default": "./lib/src/git-ignore.js"
|
|
51
|
+
},
|
|
47
52
|
"./ignore": {
|
|
48
53
|
"types": "./lib/src/ignore.d.ts",
|
|
49
54
|
"default": "./lib/src/ignore.js"
|
|
@@ -71,7 +76,7 @@
|
|
|
71
76
|
"./package.json": "./package.json"
|
|
72
77
|
}
|
|
73
78
|
},
|
|
74
|
-
"version": "0.9.
|
|
79
|
+
"version": "0.9.121",
|
|
75
80
|
"types": "./lib/index.d.ts",
|
|
76
81
|
"dbxToolsConfig": {
|
|
77
82
|
"tags": [
|
|
@@ -88,6 +93,10 @@
|
|
|
88
93
|
"types": "./lib/src/find.d.ts",
|
|
89
94
|
"default": "./lib/src/find.js"
|
|
90
95
|
},
|
|
96
|
+
"./git-ignore": {
|
|
97
|
+
"types": "./lib/src/git-ignore.d.ts",
|
|
98
|
+
"default": "./lib/src/git-ignore.js"
|
|
99
|
+
},
|
|
91
100
|
"./ignore": {
|
|
92
101
|
"types": "./lib/src/ignore.d.ts",
|
|
93
102
|
"default": "./lib/src/ignore.js"
|
package/src/find.ts
CHANGED
|
@@ -1,22 +1,29 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Repository-consistent file discovery over `glob`.
|
|
3
3
|
*
|
|
4
|
-
* Reuse {@link findFiles} when package discovery,
|
|
5
|
-
* tooling must honor the same ignore catalogue and
|
|
6
|
-
* Direct `glob` calls should be reserved for
|
|
4
|
+
* Reuse {@link findFiles} or {@link findFilesSync} when package discovery,
|
|
5
|
+
* generation, cleanup, or docs tooling must honor the same ignore catalogue and
|
|
6
|
+
* symlink defaults as watchers. Direct `glob` calls should be reserved for
|
|
7
|
+
* behavior that intentionally differs.
|
|
7
8
|
*
|
|
8
9
|
* @module
|
|
9
10
|
*/
|
|
10
11
|
|
|
11
12
|
import { object, type Sequence } from "@dbx-tools/shared-core";
|
|
12
|
-
import {
|
|
13
|
+
import {
|
|
14
|
+
globIterate,
|
|
15
|
+
globIterateSync,
|
|
16
|
+
IgnoreLike,
|
|
17
|
+
type GlobOptionsWithFileTypesUnset,
|
|
18
|
+
} from "glob";
|
|
19
|
+
import { GitIgnore } from "./git-ignore.ts";
|
|
13
20
|
import { ignorePathMatcher } from "./ignore.ts";
|
|
14
21
|
import { PathMatcher, PathMatchInput, pathMatchTests, toPathMatcher } from "./match.ts";
|
|
15
22
|
import { FileScanIgnoreOptions, FileScanOptions, FOLLOW_SYMLINKS_DEFAULT } from "./scan.ts";
|
|
16
23
|
|
|
17
24
|
type FileFindIgnore = PathMatchInput | readonly PathMatchInput[] | IgnoreLike;
|
|
18
25
|
|
|
19
|
-
/** Glob, root, ignore, and symlink options for {@link findFiles}. */
|
|
26
|
+
/** Glob, root, ignore, and symlink options for {@link findFiles} and {@link findFilesSync}. */
|
|
20
27
|
export interface FileFindOptions
|
|
21
28
|
extends
|
|
22
29
|
Omit<
|
|
@@ -33,17 +40,51 @@ export interface FileFindOptions
|
|
|
33
40
|
* in which case only that predicate applies). The ignore list mirrors what
|
|
34
41
|
* {@link watchFiles} feeds through its matchers.
|
|
35
42
|
*/
|
|
36
|
-
export function findFiles(
|
|
37
|
-
|
|
43
|
+
export async function* findFiles(
|
|
44
|
+
pattern: string | string[],
|
|
45
|
+
options?: FileFindOptions,
|
|
46
|
+
): AsyncGenerator<string> {
|
|
47
|
+
yield* globIterate(pattern, await toGlobOptions(options));
|
|
38
48
|
}
|
|
39
49
|
|
|
40
|
-
|
|
50
|
+
/** Synchronous counterpart to {@link findFiles}. */
|
|
51
|
+
export function findFilesSync(
|
|
52
|
+
pattern: string | string[],
|
|
53
|
+
options?: FileFindOptions,
|
|
54
|
+
): Sequence<string> {
|
|
55
|
+
return object.sequence(globIterateSync(pattern, toGlobOptionsSync(options)));
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
async function toGlobOptions(
|
|
59
|
+
options: FileFindOptions | undefined,
|
|
60
|
+
): Promise<GlobOptionsWithFileTypesUnset> {
|
|
61
|
+
const { cwd, ignoreOptions, followSymlinks } = options ?? {};
|
|
62
|
+
const root = cwd ?? process.cwd();
|
|
63
|
+
const gitIgnore = ignoreOptions?.git
|
|
64
|
+
? await GitIgnore.load(root, { ignoreOptions, followSymlinks })
|
|
65
|
+
: undefined;
|
|
66
|
+
return buildGlobOptions(options, gitIgnore);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function toGlobOptionsSync(options: FileFindOptions | undefined): GlobOptionsWithFileTypesUnset {
|
|
70
|
+
const { cwd, ignoreOptions, followSymlinks } = options ?? {};
|
|
71
|
+
const root = cwd ?? process.cwd();
|
|
72
|
+
const gitIgnore = ignoreOptions?.git
|
|
73
|
+
? GitIgnore.loadSync(root, { ignoreOptions, followSymlinks })
|
|
74
|
+
: undefined;
|
|
75
|
+
return buildGlobOptions(options, gitIgnore);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function buildGlobOptions(
|
|
79
|
+
options: FileFindOptions | undefined,
|
|
80
|
+
gitIgnore: GitIgnore | undefined,
|
|
81
|
+
): GlobOptionsWithFileTypesUnset {
|
|
41
82
|
const { cwd, ignore, ignoreOptions, followSymlinks, ...restOptions } = options ?? {};
|
|
42
83
|
return {
|
|
43
84
|
...restOptions,
|
|
44
85
|
cwd: cwd ?? process.cwd(),
|
|
45
86
|
follow: followSymlinks ?? FOLLOW_SYMLINKS_DEFAULT,
|
|
46
|
-
ignore: normalizeIgnore(ignore, ignoreOptions),
|
|
87
|
+
ignore: normalizeIgnore(ignore, ignoreOptions, gitIgnore),
|
|
47
88
|
};
|
|
48
89
|
}
|
|
49
90
|
|
|
@@ -66,7 +107,7 @@ function isIgnoreLike(value: unknown): value is IgnoreLike {
|
|
|
66
107
|
return false;
|
|
67
108
|
}
|
|
68
109
|
/**
|
|
69
|
-
* Builds the {@link IgnoreLike} object
|
|
110
|
+
* Builds the {@link IgnoreLike} object file discovery hands to `glob`.
|
|
70
111
|
*
|
|
71
112
|
* A caller-supplied `IgnoreLike` (an object, not string/array) is consulted
|
|
72
113
|
* first - its `ignored`/`childrenIgnored` win - after which the shared
|
|
@@ -78,6 +119,7 @@ function isIgnoreLike(value: unknown): value is IgnoreLike {
|
|
|
78
119
|
function normalizeIgnore(
|
|
79
120
|
ignore: FileFindIgnore | undefined,
|
|
80
121
|
ignoreOptions: FileScanIgnoreOptions | undefined,
|
|
122
|
+
gitIgnore: GitIgnore | undefined,
|
|
81
123
|
): IgnoreLike {
|
|
82
124
|
const ignoreLike: IgnoreLike | undefined = isIgnoreLike(ignore) ? ignore : undefined;
|
|
83
125
|
const ignorePathMatcherInputs: PathMatchInput[] | undefined =
|
|
@@ -96,6 +138,7 @@ function normalizeIgnore(
|
|
|
96
138
|
ignored(path) {
|
|
97
139
|
if (ignoreLike?.ignored?.(path)) return true;
|
|
98
140
|
const patheRelative = path.relative();
|
|
141
|
+
if (gitIgnore?.ignores(patheRelative, path.isDirectory())) return true;
|
|
99
142
|
const ignore = ignoreMatcher(patheRelative);
|
|
100
143
|
return ignore;
|
|
101
144
|
},
|
|
@@ -103,6 +146,7 @@ function normalizeIgnore(
|
|
|
103
146
|
if (ignoreLike?.childrenIgnored?.(path)) return true;
|
|
104
147
|
const patheRelative = path.relative();
|
|
105
148
|
if (patheRelative) {
|
|
149
|
+
if (gitIgnore?.ignores(patheRelative, true)) return true;
|
|
106
150
|
if (ignoreMatcher(patheRelative)) {
|
|
107
151
|
return true;
|
|
108
152
|
} else if (ignoreMatcher(patheRelative + "/")) {
|
|
@@ -131,7 +175,7 @@ if (import.meta.main) {
|
|
|
131
175
|
test: true,
|
|
132
176
|
},
|
|
133
177
|
});
|
|
134
|
-
for (const file of files) {
|
|
178
|
+
for await (const file of files) {
|
|
135
179
|
console.log(file);
|
|
136
180
|
}
|
|
137
181
|
const elapsed = performance.now() - startTime;
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mutable, Git-compatible `.gitignore` path matching.
|
|
3
|
+
*
|
|
4
|
+
* Rule syntax is owned by the `ignore` package, whose compatibility suite
|
|
5
|
+
* compares behavior with `git check-ignore`. This module adds repository and
|
|
6
|
+
* nested-file scoping plus in-memory add, update, and removal.
|
|
7
|
+
*
|
|
8
|
+
* @module
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { readFileSync } from "node:fs";
|
|
12
|
+
import { readFile } from "node:fs/promises";
|
|
13
|
+
import { basename, dirname, isAbsolute, relative, resolve, sep } from "node:path";
|
|
14
|
+
import { fileURLToPath } from "node:url";
|
|
15
|
+
import { glob, globSync, type IgnoreLike } from "glob";
|
|
16
|
+
import ignore from "ignore";
|
|
17
|
+
import type { IgnorePatternOptions } from "./ignore.ts";
|
|
18
|
+
import { ignorePathMatcher } from "./ignore.ts";
|
|
19
|
+
import { toPathMatcher, type PathMatcher } from "./match.ts";
|
|
20
|
+
|
|
21
|
+
interface GitIgnoreRuleSet {
|
|
22
|
+
content: string;
|
|
23
|
+
directory: string;
|
|
24
|
+
matcher: ReturnType<typeof ignore>;
|
|
25
|
+
path: string;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** Options used while discovering `.gitignore` files beneath a root. */
|
|
29
|
+
export interface GitIgnoreLoadOptions {
|
|
30
|
+
/** Built-in directory groups pruned while looking for ignore files. */
|
|
31
|
+
ignoreOptions?: IgnorePatternOptions;
|
|
32
|
+
/** Follow symlinked directories during discovery. Defaults to false. */
|
|
33
|
+
followSymlinks?: boolean;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** Mutable path predicate composed from root and nested `.gitignore` files. */
|
|
37
|
+
export class GitIgnore {
|
|
38
|
+
readonly root: string;
|
|
39
|
+
/** Stable composable matcher that observes later {@link set}, {@link delete}, and {@link clear} calls. */
|
|
40
|
+
readonly matcher: PathMatcher = toPathMatcher((path) => this.ignores(path));
|
|
41
|
+
|
|
42
|
+
private readonly files = new Map<string, GitIgnoreRuleSet>();
|
|
43
|
+
private rules: GitIgnoreRuleSet[] = [];
|
|
44
|
+
|
|
45
|
+
constructor(root: string | URL) {
|
|
46
|
+
this.root = resolve(root instanceof URL ? fileURLToPath(root) : root);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** Load every applicable `.gitignore` beneath {@link root}. */
|
|
50
|
+
static async load(
|
|
51
|
+
root: string | URL,
|
|
52
|
+
options: GitIgnoreLoadOptions = {},
|
|
53
|
+
): Promise<GitIgnore> {
|
|
54
|
+
const result = new GitIgnore(root);
|
|
55
|
+
for (const path of await glob("**/.gitignore", discoveryOptions(result.root, options))) {
|
|
56
|
+
result.set(path, await readFile(resolve(result.root, path), "utf8"));
|
|
57
|
+
}
|
|
58
|
+
return result;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/** Synchronous counterpart to {@link GitIgnore.load}. */
|
|
62
|
+
static loadSync(root: string | URL, options: GitIgnoreLoadOptions = {}): GitIgnore {
|
|
63
|
+
const result = new GitIgnore(root);
|
|
64
|
+
for (const path of globSync("**/.gitignore", discoveryOptions(result.root, options))) {
|
|
65
|
+
result.set(path, readFileSync(resolve(result.root, path), "utf8"));
|
|
66
|
+
}
|
|
67
|
+
return result;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/** Whether `path` names a `.gitignore` control file. */
|
|
71
|
+
static isFile(path: string): boolean {
|
|
72
|
+
return basename(path) === ".gitignore";
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/** Add or replace one `.gitignore` file and its in-memory content. */
|
|
76
|
+
set(path: string, content: string): void {
|
|
77
|
+
const relativePath = this.relativePath(path);
|
|
78
|
+
if (!relativePath || !GitIgnore.isFile(relativePath)) {
|
|
79
|
+
throw new TypeError(`Git ignore path must name a .gitignore under ${this.root}: ${path}`);
|
|
80
|
+
}
|
|
81
|
+
this.files.set(relativePath, {
|
|
82
|
+
content,
|
|
83
|
+
directory: toPosix(dirname(relativePath)) === "." ? "" : toPosix(dirname(relativePath)),
|
|
84
|
+
matcher: ignore().add(content),
|
|
85
|
+
path: relativePath,
|
|
86
|
+
});
|
|
87
|
+
this.refreshRules();
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/** Remove one `.gitignore` file. Returns whether it was registered. */
|
|
91
|
+
delete(path: string): boolean {
|
|
92
|
+
const relativePath = this.relativePath(path);
|
|
93
|
+
if (!relativePath) return false;
|
|
94
|
+
const deleted = this.files.delete(relativePath);
|
|
95
|
+
if (deleted) this.refreshRules();
|
|
96
|
+
return deleted;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/** Remove every registered `.gitignore`. */
|
|
100
|
+
clear(): void {
|
|
101
|
+
this.files.clear();
|
|
102
|
+
this.rules = [];
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/** Return the retained content for a registered `.gitignore`. */
|
|
106
|
+
get(path: string): string | undefined {
|
|
107
|
+
const relativePath = this.relativePath(path);
|
|
108
|
+
return relativePath ? this.files.get(relativePath)?.content : undefined;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/** Whether a path is ignored after applying parent then nested rule files. */
|
|
112
|
+
ignores(path: string, directory: boolean = false): boolean {
|
|
113
|
+
const relativePath = this.relativePath(path);
|
|
114
|
+
if (!relativePath || relativePath === ".") return false;
|
|
115
|
+
let ignored = false;
|
|
116
|
+
for (const rules of this.rules) {
|
|
117
|
+
const scopedPath = pathWithin(rules.directory, relativePath);
|
|
118
|
+
if (scopedPath === undefined || scopedPath === "") continue;
|
|
119
|
+
if (ignoredParent(rules.matcher, scopedPath)) return true;
|
|
120
|
+
const result = rules.matcher.test(directory ? `${trimSlash(scopedPath)}/` : scopedPath);
|
|
121
|
+
if (result.ignored) ignored = true;
|
|
122
|
+
if (result.unignored) ignored = false;
|
|
123
|
+
}
|
|
124
|
+
return ignored;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
private relativePath(path: string): string | undefined {
|
|
128
|
+
const absolute = isAbsolute(path) ? resolve(path) : resolve(this.root, path);
|
|
129
|
+
const relativePath = relative(this.root, absolute);
|
|
130
|
+
if (relativePath === "" || relativePath === ".") return ".";
|
|
131
|
+
if (relativePath === ".." || relativePath.startsWith(`..${sep}`) || isAbsolute(relativePath)) {
|
|
132
|
+
return undefined;
|
|
133
|
+
}
|
|
134
|
+
return toPosix(relativePath);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
private refreshRules(): void {
|
|
138
|
+
this.rules = [...this.files.values()].sort(
|
|
139
|
+
(left, right) =>
|
|
140
|
+
pathDepth(left.directory) - pathDepth(right.directory) ||
|
|
141
|
+
left.path.localeCompare(right.path),
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function discoveryOptions(
|
|
147
|
+
root: string,
|
|
148
|
+
options: GitIgnoreLoadOptions,
|
|
149
|
+
): {
|
|
150
|
+
cwd: string;
|
|
151
|
+
dot: true;
|
|
152
|
+
follow: boolean;
|
|
153
|
+
ignore: IgnoreLike;
|
|
154
|
+
nodir: true;
|
|
155
|
+
} {
|
|
156
|
+
const matcher = ignorePathMatcher(options.ignoreOptions);
|
|
157
|
+
return {
|
|
158
|
+
cwd: root,
|
|
159
|
+
dot: true,
|
|
160
|
+
follow: options.followSymlinks ?? false,
|
|
161
|
+
ignore: {
|
|
162
|
+
ignored(path) {
|
|
163
|
+
const relativePath = path.relative();
|
|
164
|
+
return !GitIgnore.isFile(relativePath) && matcher(relativePath);
|
|
165
|
+
},
|
|
166
|
+
childrenIgnored(path) {
|
|
167
|
+
const relativePath = path.relative();
|
|
168
|
+
return matcher(relativePath) || matcher(`${relativePath}/`);
|
|
169
|
+
},
|
|
170
|
+
},
|
|
171
|
+
nodir: true,
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
function ignoredParent(matcher: ReturnType<typeof ignore>, path: string): boolean {
|
|
176
|
+
const segments = trimSlash(path).split("/");
|
|
177
|
+
const parentCount = segments.length - 1;
|
|
178
|
+
for (let index = 1; index <= parentCount; index++) {
|
|
179
|
+
if (matcher.test(`${segments.slice(0, index).join("/")}/`).ignored) return true;
|
|
180
|
+
}
|
|
181
|
+
return false;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
function pathWithin(directory: string, path: string): string | undefined {
|
|
185
|
+
if (!directory) return path;
|
|
186
|
+
if (path === directory) return "";
|
|
187
|
+
return path.startsWith(`${directory}/`) ? path.slice(directory.length + 1) : undefined;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
function pathDepth(path: string): number {
|
|
191
|
+
return path ? path.split("/").length : 0;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
function trimSlash(path: string): string {
|
|
195
|
+
return path.replace(/^\/+|\/+$/g, "");
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
function toPosix(path: string): string {
|
|
199
|
+
return path.split(sep).join("/");
|
|
200
|
+
}
|
package/src/scan.ts
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* @module
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
import { IgnorePatternOptions } from "./ignore.ts";
|
|
11
|
+
import type { IgnorePatternOptions } from "./ignore.ts";
|
|
12
12
|
import { PathMatchInput } from "./match.ts";
|
|
13
13
|
|
|
14
14
|
/** Shared default used by file discovery and watching to avoid traversing symlinks. */
|
|
@@ -43,5 +43,11 @@ export interface FileScanOptions {
|
|
|
43
43
|
signal?: AbortSignal;
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
/** Options controlling
|
|
47
|
-
export
|
|
46
|
+
/** Options controlling built-in and repository `.gitignore` matching. */
|
|
47
|
+
export interface FileScanIgnoreOptions extends IgnorePatternOptions {
|
|
48
|
+
/**
|
|
49
|
+
* Load root and nested `.gitignore` files using Git-compatible semantics.
|
|
50
|
+
* Defaults to false.
|
|
51
|
+
*/
|
|
52
|
+
git?: boolean;
|
|
53
|
+
}
|