UNPKG

8.55 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3exports.Glob = void 0;
4const minimatch_1 = require("minimatch");
5const node_url_1 = require("node:url");
6const path_scurry_1 = require("path-scurry");
7const pattern_js_1 = require("./pattern.js");
8const walker_js_1 = require("./walker.js");
9// if no process global, just call it linux.
10// so we default to case-sensitive, / separators
11const defaultPlatform = (typeof process === 'object' &&
12 process &&
13 typeof process.platform === 'string') ?
14 process.platform
15 : 'linux';
16/**
17 * An object that can perform glob pattern traversals.
18 */
19class Glob {
20 absolute;
21 cwd;
22 root;
23 dot;
24 dotRelative;
25 follow;
26 ignore;
27 magicalBraces;
28 mark;
29 matchBase;
30 maxDepth;
31 nobrace;
32 nocase;
33 nodir;
34 noext;
35 noglobstar;
36 pattern;
37 platform;
38 realpath;
39 scurry;
40 stat;
41 signal;
42 windowsPathsNoEscape;
43 withFileTypes;
44 includeChildMatches;
45 /**
46 * The options provided to the constructor.
47 */
48 opts;
49 /**
50 * An array of parsed immutable {@link Pattern} objects.
51 */
52 patterns;
53 /**
54 * All options are stored as properties on the `Glob` object.
55 *
56 * See {@link GlobOptions} for full options descriptions.
57 *
58 * Note that a previous `Glob` object can be passed as the
59 * `GlobOptions` to another `Glob` instantiation to re-use settings
60 * and caches with a new pattern.
61 *
62 * Traversal functions can be called multiple times to run the walk
63 * again.
64 */
65 constructor(pattern, opts) {
66 /* c8 ignore start */
67 if (!opts)
68 throw new TypeError('glob options required');
69 /* c8 ignore stop */
70 this.withFileTypes = !!opts.withFileTypes;
71 this.signal = opts.signal;
72 this.follow = !!opts.follow;
73 this.dot = !!opts.dot;
74 this.dotRelative = !!opts.dotRelative;
75 this.nodir = !!opts.nodir;
76 this.mark = !!opts.mark;
77 if (!opts.cwd) {
78 this.cwd = '';
79 }
80 else if (opts.cwd instanceof URL || opts.cwd.startsWith('file://')) {
81 opts.cwd = (0, node_url_1.fileURLToPath)(opts.cwd);
82 }
83 this.cwd = opts.cwd || '';
84 this.root = opts.root;
85 this.magicalBraces = !!opts.magicalBraces;
86 this.nobrace = !!opts.nobrace;
87 this.noext = !!opts.noext;
88 this.realpath = !!opts.realpath;
89 this.absolute = opts.absolute;
90 this.includeChildMatches = opts.includeChildMatches !== false;
91 this.noglobstar = !!opts.noglobstar;
92 this.matchBase = !!opts.matchBase;
93 this.maxDepth =
94 typeof opts.maxDepth === 'number' ? opts.maxDepth : Infinity;
95 this.stat = !!opts.stat;
96 this.ignore = opts.ignore;
97 if (this.withFileTypes && this.absolute !== undefined) {
98 throw new Error('cannot set absolute and withFileTypes:true');
99 }
100 if (typeof pattern === 'string') {
101 pattern = [pattern];
102 }
103 this.windowsPathsNoEscape =
104 !!opts.windowsPathsNoEscape ||
105 opts.allowWindowsEscape ===
106 false;
107 if (this.windowsPathsNoEscape) {
108 pattern = pattern.map(p => p.replace(/\\/g, '/'));
109 }
110 if (this.matchBase) {
111 if (opts.noglobstar) {
112 throw new TypeError('base matching requires globstar');
113 }
114 pattern = pattern.map(p => (p.includes('/') ? p : `./**/${p}`));
115 }
116 this.pattern = pattern;
117 this.platform = opts.platform || defaultPlatform;
118 this.opts = { ...opts, platform: this.platform };
119 if (opts.scurry) {
120 this.scurry = opts.scurry;
121 if (opts.nocase !== undefined &&
122 opts.nocase !== opts.scurry.nocase) {
123 throw new Error('nocase option contradicts provided scurry option');
124 }
125 }
126 else {
127 const Scurry = opts.platform === 'win32' ? path_scurry_1.PathScurryWin32
128 : opts.platform === 'darwin' ? path_scurry_1.PathScurryDarwin
129 : opts.platform ? path_scurry_1.PathScurryPosix
130 : path_scurry_1.PathScurry;
131 this.scurry = new Scurry(this.cwd, {
132 nocase: opts.nocase,
133 fs: opts.fs,
134 });
135 }
136 this.nocase = this.scurry.nocase;
137 // If you do nocase:true on a case-sensitive file system, then
138 // we need to use regexps instead of strings for non-magic
139 // path portions, because statting `aBc` won't return results
140 // for the file `AbC` for example.
141 const nocaseMagicOnly = this.platform === 'darwin' || this.platform === 'win32';
142 const mmo = {
143 // default nocase based on platform
144 ...opts,
145 dot: this.dot,
146 matchBase: this.matchBase,
147 nobrace: this.nobrace,
148 nocase: this.nocase,
149 nocaseMagicOnly,
150 nocomment: true,
151 noext: this.noext,
152 nonegate: true,
153 optimizationLevel: 2,
154 platform: this.platform,
155 windowsPathsNoEscape: this.windowsPathsNoEscape,
156 debug: !!this.opts.debug,
157 };
158 const mms = this.pattern.map(p => new minimatch_1.Minimatch(p, mmo));
159 const [matchSet, globParts] = mms.reduce((set, m) => {
160 set[0].push(...m.set);
161 set[1].push(...m.globParts);
162 return set;
163 }, [[], []]);
164 this.patterns = matchSet.map((set, i) => {
165 const g = globParts[i];
166 /* c8 ignore start */
167 if (!g)
168 throw new Error('invalid pattern object');
169 /* c8 ignore stop */
170 return new pattern_js_1.Pattern(set, g, 0, this.platform);
171 });
172 }
173 async walk() {
174 // Walkers always return array of Path objects, so we just have to
175 // coerce them into the right shape. It will have already called
176 // realpath() if the option was set to do so, so we know that's cached.
177 // start out knowing the cwd, at least
178 return [
179 ...(await new walker_js_1.GlobWalker(this.patterns, this.scurry.cwd, {
180 ...this.opts,
181 maxDepth: this.maxDepth !== Infinity ?
182 this.maxDepth + this.scurry.cwd.depth()
183 : Infinity,
184 platform: this.platform,
185 nocase: this.nocase,
186 includeChildMatches: this.includeChildMatches,
187 }).walk()),
188 ];
189 }
190 walkSync() {
191 return [
192 ...new walker_js_1.GlobWalker(this.patterns, this.scurry.cwd, {
193 ...this.opts,
194 maxDepth: this.maxDepth !== Infinity ?
195 this.maxDepth + this.scurry.cwd.depth()
196 : Infinity,
197 platform: this.platform,
198 nocase: this.nocase,
199 includeChildMatches: this.includeChildMatches,
200 }).walkSync(),
201 ];
202 }
203 stream() {
204 return new walker_js_1.GlobStream(this.patterns, this.scurry.cwd, {
205 ...this.opts,
206 maxDepth: this.maxDepth !== Infinity ?
207 this.maxDepth + this.scurry.cwd.depth()
208 : Infinity,
209 platform: this.platform,
210 nocase: this.nocase,
211 includeChildMatches: this.includeChildMatches,
212 }).stream();
213 }
214 streamSync() {
215 return new walker_js_1.GlobStream(this.patterns, this.scurry.cwd, {
216 ...this.opts,
217 maxDepth: this.maxDepth !== Infinity ?
218 this.maxDepth + this.scurry.cwd.depth()
219 : Infinity,
220 platform: this.platform,
221 nocase: this.nocase,
222 includeChildMatches: this.includeChildMatches,
223 }).streamSync();
224 }
225 /**
226 * Default sync iteration function. Returns a Generator that
227 * iterates over the results.
228 */
229 iterateSync() {
230 return this.streamSync()[Symbol.iterator]();
231 }
232 [Symbol.iterator]() {
233 return this.iterateSync();
234 }
235 /**
236 * Default async iteration function. Returns an AsyncGenerator that
237 * iterates over the results.
238 */
239 iterate() {
240 return this.stream()[Symbol.asyncIterator]();
241 }
242 [Symbol.asyncIterator]() {
243 return this.iterate();
244 }
245}
246exports.Glob = Glob;
247//# sourceMappingURL=glob.js.map
\No newline at end of file