1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3exports.Glob = void 0;
4const minimatch_1 = require("minimatch");
5const path_scurry_1 = require("path-scurry");
6const url_1 = require("url");
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    /**
45     * The options provided to the constructor.
46     */
47    opts;
48    /**
49     * An array of parsed immutable {@link Pattern} objects.
50     */
51    patterns;
52    /**
53     * All options are stored as properties on the `Glob` object.
54     *
55     * See {@link GlobOptions} for full options descriptions.
56     *
57     * Note that a previous `Glob` object can be passed as the
58     * `GlobOptions` to another `Glob` instantiation to re-use settings
59     * and caches with a new pattern.
60     *
61     * Traversal functions can be called multiple times to run the walk
62     * again.
63     */
64    constructor(pattern, opts) {
65        /* c8 ignore start */
66        if (!opts)
67            throw new TypeError('glob options required');
68        /* c8 ignore stop */
69        this.withFileTypes = !!opts.withFileTypes;
70        this.signal = opts.signal;
71        this.follow = !!opts.follow;
72        this.dot = !!opts.dot;
73        this.dotRelative = !!opts.dotRelative;
74        this.nodir = !!opts.nodir;
75        this.mark = !!opts.mark;
76        if (!opts.cwd) {
77            this.cwd = '';
78        }
79        else if (opts.cwd instanceof URL || opts.cwd.startsWith('file://')) {
80            opts.cwd = (0, url_1.fileURLToPath)(opts.cwd);
81        }
82        this.cwd = opts.cwd || '';
83        this.root = opts.root;
84        this.magicalBraces = !!opts.magicalBraces;
85        this.nobrace = !!opts.nobrace;
86        this.noext = !!opts.noext;
87        this.realpath = !!opts.realpath;
88        this.absolute = opts.absolute;
89        this.noglobstar = !!opts.noglobstar;
90        this.matchBase = !!opts.matchBase;
91        this.maxDepth =
92            typeof opts.maxDepth === 'number' ? opts.maxDepth : Infinity;
93        this.stat = !!opts.stat;
94        this.ignore = opts.ignore;
95        if (this.withFileTypes && this.absolute !== undefined) {
96            throw new Error('cannot set absolute and withFileTypes:true');
97        }
98        if (typeof pattern === 'string') {
99            pattern = [pattern];
100        }
101        this.windowsPathsNoEscape =
102            !!opts.windowsPathsNoEscape ||
103                opts.allowWindowsEscape === false;
104        if (this.windowsPathsNoEscape) {
105            pattern = pattern.map(p => p.replace(/\\/g, '/'));
106        }
107        if (this.matchBase) {
108            if (opts.noglobstar) {
109                throw new TypeError('base matching requires globstar');
110            }
111            pattern = pattern.map(p => (p.includes('/') ? p : `./**/${p}`));
112        }
113        this.pattern = pattern;
114        this.platform = opts.platform || defaultPlatform;
115        this.opts = { ...opts, platform: this.platform };
116        if (opts.scurry) {
117            this.scurry = opts.scurry;
118            if (opts.nocase !== undefined &&
119                opts.nocase !== opts.scurry.nocase) {
120                throw new Error('nocase option contradicts provided scurry option');
121            }
122        }
123        else {
124            const Scurry = opts.platform === 'win32'
125                ? path_scurry_1.PathScurryWin32
126                : opts.platform === 'darwin'
127                    ? path_scurry_1.PathScurryDarwin
128                    : opts.platform
129                        ? 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            }).walk()),
187        ];
188    }
189    walkSync() {
190        return [
191            ...new walker_js_1.GlobWalker(this.patterns, this.scurry.cwd, {
192                ...this.opts,
193                maxDepth: this.maxDepth !== Infinity
194                    ? this.maxDepth + this.scurry.cwd.depth()
195                    : Infinity,
196                platform: this.platform,
197                nocase: this.nocase,
198            }).walkSync(),
199        ];
200    }
201    stream() {
202        return new walker_js_1.GlobStream(this.patterns, this.scurry.cwd, {
203            ...this.opts,
204            maxDepth: this.maxDepth !== Infinity
205                ? this.maxDepth + this.scurry.cwd.depth()
206                : Infinity,
207            platform: this.platform,
208            nocase: this.nocase,
209        }).stream();
210    }
211    streamSync() {
212        return new walker_js_1.GlobStream(this.patterns, this.scurry.cwd, {
213            ...this.opts,
214            maxDepth: this.maxDepth !== Infinity
215                ? this.maxDepth + this.scurry.cwd.depth()
216                : Infinity,
217            platform: this.platform,
218            nocase: this.nocase,
219        }).streamSync();
220    }
221    /**
222     * Default sync iteration function. Returns a Generator that
223     * iterates over the results.
224     */
225    iterateSync() {
226        return this.streamSync()[Symbol.iterator]();
227    }
228    [Symbol.iterator]() {
229        return this.iterateSync();
230    }
231    /**
232     * Default async iteration function. Returns an AsyncGenerator that
233     * iterates over the results.
234     */
235    iterate() {
236        return this.stream()[Symbol.asyncIterator]();
237    }
238    [Symbol.asyncIterator]() {
239        return this.iterate();
240    }
241}
242exports.Glob = Glob;
243//# sourceMappingURL=glob.js.map