diff --git a/README.md b/README.md index 216b55b..8e28949 100644 --- a/README.md +++ b/README.md @@ -73,7 +73,7 @@ permissions: | Name | Default | Description | |---------------------------|---------------------------------------|------------------------------------------------------------------------------------------------------------------| -| `metafiles` | - | A required comma-separated list of paths to [esbuild's meta file]([https://esbuild.github.io/api/#metafile]). | +| `metafiles` | - | A required comma-separated list of paths to [esbuild's meta file]([https://esbuild.github.io/api/#metafile]). Glob (`dist/**/meta.json`) is supported. | | `name` | ${{ github.event.
repository.name }} | The name of your project. This will be used in the comment header. | | `analyze_directory` | `.analyzer` | A path to working directory where bundle analysis are stored. | | `include_extensions` | `.js,.cjs,.mjs` | A comma-separated list of file extension to be included in the analysis table. | diff --git a/__tests__/__fixtures__/examples/basic/esbuild.mjs b/__tests__/__fixtures__/examples/basic/esbuild.mjs index cc48781..aa3cf70 100644 --- a/__tests__/__fixtures__/examples/basic/esbuild.mjs +++ b/__tests__/__fixtures__/examples/basic/esbuild.mjs @@ -1,4 +1,4 @@ -import { writeFileSync } from "node:fs"; +import {mkdirSync, writeFileSync} from "node:fs"; import { build } from "esbuild"; const result = await build({ @@ -17,4 +17,5 @@ const result = await build({ assetNames: "resources/[name]-[hash]", }); -writeFileSync(`out/meta.json`, JSON.stringify(result.metafile, null, 2)); +mkdirSync(`out/foo`, { recursive: true }); +writeFileSync(`out/foo/meta.json`, JSON.stringify(result.metafile, null, 2)); diff --git a/__tests__/__fixtures__/examples/multi-outputs/esbuild.mjs b/__tests__/__fixtures__/examples/multi-outputs/esbuild.mjs index 9433503..14c9fe8 100644 --- a/__tests__/__fixtures__/examples/multi-outputs/esbuild.mjs +++ b/__tests__/__fixtures__/examples/multi-outputs/esbuild.mjs @@ -1,4 +1,4 @@ -import { writeFileSync } from "node:fs"; +import { writeFileSync, mkdirSync } from "node:fs"; import { build } from "esbuild"; const result = await build({ @@ -17,4 +17,5 @@ const result = await build({ assetNames: "resources/[name]-[hash]", }); -writeFileSync(`out/meta.json`, JSON.stringify(result.metafile, null, 2)); +mkdirSync(`out/bar`, { recursive: true }); +writeFileSync(`out/bar/meta.json`, JSON.stringify(result.metafile, null, 2)); diff --git a/__tests__/no-base.test.ts b/__tests__/no-base.test.ts index a7d83df..9099a5f 100644 --- a/__tests__/no-base.test.ts +++ b/__tests__/no-base.test.ts @@ -18,7 +18,7 @@ describe("examples w/o base analysis", () => { analyzerDirectory: ".analyzer", percentExtraAttention: 20, includeExtensions: [".js", ".mjs", ".cjs"], - metafiles: ["out/meta.json"], + metafiles: ["out/**/meta.json"], name: "test", showDetails: false, }; diff --git a/action.yaml b/action.yaml index b49cee5..3408d79 100644 --- a/action.yaml +++ b/action.yaml @@ -9,7 +9,9 @@ inputs: metafiles: required: true description: | - A comma-separated list of paths to [esbuild's meta file]([https://esbuild.github.io/api/#metafile]). Must be non-empty. + A comma-separated list of paths to [esbuild's meta file]([https://esbuild.github.io/api/#metafile]). + Must be non-empty. + Glob (`dist/**/meta.json`) is supported. As of esbuild v0.20.0, you need to write the meta file by yourself after build, something like this: diff --git a/dist/index.mjs b/dist/index.mjs index f20e162..7fe76b8 100644 --- a/dist/index.mjs +++ b/dist/index.mjs @@ -1,26 +1,6566 @@ +var __create = Object.create; +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __getProtoOf = Object.getPrototypeOf; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __commonJS = (cb, mod) => function __require() { + return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports; +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( + // If the importer is in node compatibility mode or this is not an ESM + // file that has been converted to a CommonJS file using a Babel- + // compatible transform (i.e. "__esModule" has not been set), then set + // "default" to the CommonJS "module.exports" for node compatibility. + isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, + mod +)); + +// node_modules/balanced-match/index.js +var require_balanced_match = __commonJS({ + "node_modules/balanced-match/index.js"(exports, module) { + "use strict"; + module.exports = balanced; + function balanced(a, b, str) { + if (a instanceof RegExp) + a = maybeMatch(a, str); + if (b instanceof RegExp) + b = maybeMatch(b, str); + var r = range(a, b, str); + return r && { + start: r[0], + end: r[1], + pre: str.slice(0, r[0]), + body: str.slice(r[0] + a.length, r[1]), + post: str.slice(r[1] + b.length) + }; + } + function maybeMatch(reg, str) { + var m = str.match(reg); + return m ? m[0] : null; + } + balanced.range = range; + function range(a, b, str) { + var begs, beg, left, right, result; + var ai = str.indexOf(a); + var bi = str.indexOf(b, ai + 1); + var i = ai; + if (ai >= 0 && bi > 0) { + if (a === b) { + return [ai, bi]; + } + begs = []; + left = str.length; + while (i >= 0 && !result) { + if (i == ai) { + begs.push(i); + ai = str.indexOf(a, i + 1); + } else if (begs.length == 1) { + result = [begs.pop(), bi]; + } else { + beg = begs.pop(); + if (beg < left) { + left = beg; + right = bi; + } + bi = str.indexOf(b, i + 1); + } + i = ai < bi && ai >= 0 ? ai : bi; + } + if (begs.length) { + result = [left, right]; + } + } + return result; + } + } +}); + +// node_modules/brace-expansion/index.js +var require_brace_expansion = __commonJS({ + "node_modules/brace-expansion/index.js"(exports, module) { + var balanced = require_balanced_match(); + module.exports = expandTop; + var escSlash = "\0SLASH" + Math.random() + "\0"; + var escOpen = "\0OPEN" + Math.random() + "\0"; + var escClose = "\0CLOSE" + Math.random() + "\0"; + var escComma = "\0COMMA" + Math.random() + "\0"; + var escPeriod = "\0PERIOD" + Math.random() + "\0"; + function numeric(str) { + return parseInt(str, 10) == str ? parseInt(str, 10) : str.charCodeAt(0); + } + function escapeBraces(str) { + return str.split("\\\\").join(escSlash).split("\\{").join(escOpen).split("\\}").join(escClose).split("\\,").join(escComma).split("\\.").join(escPeriod); + } + function unescapeBraces(str) { + return str.split(escSlash).join("\\").split(escOpen).join("{").split(escClose).join("}").split(escComma).join(",").split(escPeriod).join("."); + } + function parseCommaParts(str) { + if (!str) + return [""]; + var parts = []; + var m = balanced("{", "}", str); + if (!m) + return str.split(","); + var pre = m.pre; + var body = m.body; + var post = m.post; + var p = pre.split(","); + p[p.length - 1] += "{" + body + "}"; + var postParts = parseCommaParts(post); + if (post.length) { + p[p.length - 1] += postParts.shift(); + p.push.apply(p, postParts); + } + parts.push.apply(parts, p); + return parts; + } + function expandTop(str) { + if (!str) + return []; + if (str.substr(0, 2) === "{}") { + str = "\\{\\}" + str.substr(2); + } + return expand2(escapeBraces(str), true).map(unescapeBraces); + } + function embrace(str) { + return "{" + str + "}"; + } + function isPadded(el) { + return /^-?0\d/.test(el); + } + function lte(i, y) { + return i <= y; + } + function gte(i, y) { + return i >= y; + } + function expand2(str, isTop) { + var expansions = []; + var m = balanced("{", "}", str); + if (!m) + return [str]; + var pre = m.pre; + var post = m.post.length ? expand2(m.post, false) : [""]; + if (/\$$/.test(m.pre)) { + for (var k = 0; k < post.length; k++) { + var expansion = pre + "{" + m.body + "}" + post[k]; + expansions.push(expansion); + } + } else { + var isNumericSequence = /^-?\d+\.\.-?\d+(?:\.\.-?\d+)?$/.test(m.body); + var isAlphaSequence = /^[a-zA-Z]\.\.[a-zA-Z](?:\.\.-?\d+)?$/.test(m.body); + var isSequence = isNumericSequence || isAlphaSequence; + var isOptions = m.body.indexOf(",") >= 0; + if (!isSequence && !isOptions) { + if (m.post.match(/,.*\}/)) { + str = m.pre + "{" + m.body + escClose + m.post; + return expand2(str); + } + return [str]; + } + var n; + if (isSequence) { + n = m.body.split(/\.\./); + } else { + n = parseCommaParts(m.body); + if (n.length === 1) { + n = expand2(n[0], false).map(embrace); + if (n.length === 1) { + return post.map(function(p) { + return m.pre + n[0] + p; + }); + } + } + } + var N; + if (isSequence) { + var x = numeric(n[0]); + var y = numeric(n[1]); + var width = Math.max(n[0].length, n[1].length); + var incr = n.length == 3 ? Math.abs(numeric(n[2])) : 1; + var test = lte; + var reverse = y < x; + if (reverse) { + incr *= -1; + test = gte; + } + var pad = n.some(isPadded); + N = []; + for (var i = x; test(i, y); i += incr) { + var c; + if (isAlphaSequence) { + c = String.fromCharCode(i); + if (c === "\\") + c = ""; + } else { + c = String(i); + if (pad) { + var need = width - c.length; + if (need > 0) { + var z = new Array(need + 1).join("0"); + if (i < 0) + c = "-" + z + c.slice(1); + else + c = z + c; + } + } + } + N.push(c); + } + } else { + N = []; + for (var j = 0; j < n.length; j++) { + N.push.apply(N, expand2(n[j], false)); + } + } + for (var j = 0; j < N.length; j++) { + for (var k = 0; k < post.length; k++) { + var expansion = pre + N[j] + post[k]; + if (!isTop || isSequence || expansion) + expansions.push(expansion); + } + } + } + return expansions; + } + } +}); + // src/index.ts import { pathToFileURL } from "node:url"; -// src/compare.ts -import fs2 from "node:fs"; -import path from "node:path"; +// src/compare.ts +import fs3 from "node:fs"; +import path3 from "node:path"; + +// src/report.ts +import fs2 from "node:fs"; +import path2 from "node:path"; +import process2 from "node:process"; +import * as console2 from "node:console"; + +// node_modules/minimatch/dist/esm/index.js +var import_brace_expansion = __toESM(require_brace_expansion(), 1); + +// node_modules/minimatch/dist/esm/assert-valid-pattern.js +var MAX_PATTERN_LENGTH = 1024 * 64; +var assertValidPattern = (pattern) => { + if (typeof pattern !== "string") { + throw new TypeError("invalid pattern"); + } + if (pattern.length > MAX_PATTERN_LENGTH) { + throw new TypeError("pattern is too long"); + } +}; + +// node_modules/minimatch/dist/esm/brace-expressions.js +var posixClasses = { + "[:alnum:]": ["\\p{L}\\p{Nl}\\p{Nd}", true], + "[:alpha:]": ["\\p{L}\\p{Nl}", true], + "[:ascii:]": ["\\x00-\\x7f", false], + "[:blank:]": ["\\p{Zs}\\t", true], + "[:cntrl:]": ["\\p{Cc}", true], + "[:digit:]": ["\\p{Nd}", true], + "[:graph:]": ["\\p{Z}\\p{C}", true, true], + "[:lower:]": ["\\p{Ll}", true], + "[:print:]": ["\\p{C}", true], + "[:punct:]": ["\\p{P}", true], + "[:space:]": ["\\p{Z}\\t\\r\\n\\v\\f", true], + "[:upper:]": ["\\p{Lu}", true], + "[:word:]": ["\\p{L}\\p{Nl}\\p{Nd}\\p{Pc}", true], + "[:xdigit:]": ["A-Fa-f0-9", false] +}; +var braceEscape = (s) => s.replace(/[[\]\\-]/g, "\\$&"); +var regexpEscape = (s) => s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"); +var rangesToString = (ranges) => ranges.join(""); +var parseClass = (glob2, position) => { + const pos = position; + if (glob2.charAt(pos) !== "[") { + throw new Error("not in a brace expression"); + } + const ranges = []; + const negs = []; + let i = pos + 1; + let sawStart = false; + let uflag = false; + let escaping = false; + let negate = false; + let endPos = pos; + let rangeStart = ""; + WHILE: + while (i < glob2.length) { + const c = glob2.charAt(i); + if ((c === "!" || c === "^") && i === pos + 1) { + negate = true; + i++; + continue; + } + if (c === "]" && sawStart && !escaping) { + endPos = i + 1; + break; + } + sawStart = true; + if (c === "\\") { + if (!escaping) { + escaping = true; + i++; + continue; + } + } + if (c === "[" && !escaping) { + for (const [cls, [unip, u, neg]] of Object.entries(posixClasses)) { + if (glob2.startsWith(cls, i)) { + if (rangeStart) { + return ["$.", false, glob2.length - pos, true]; + } + i += cls.length; + if (neg) + negs.push(unip); + else + ranges.push(unip); + uflag = uflag || u; + continue WHILE; + } + } + } + escaping = false; + if (rangeStart) { + if (c > rangeStart) { + ranges.push(braceEscape(rangeStart) + "-" + braceEscape(c)); + } else if (c === rangeStart) { + ranges.push(braceEscape(c)); + } + rangeStart = ""; + i++; + continue; + } + if (glob2.startsWith("-]", i + 1)) { + ranges.push(braceEscape(c + "-")); + i += 2; + continue; + } + if (glob2.startsWith("-", i + 1)) { + rangeStart = c; + i += 2; + continue; + } + ranges.push(braceEscape(c)); + i++; + } + if (endPos < i) { + return ["", false, 0, false]; + } + if (!ranges.length && !negs.length) { + return ["$.", false, glob2.length - pos, true]; + } + if (negs.length === 0 && ranges.length === 1 && /^\\?.$/.test(ranges[0]) && !negate) { + const r = ranges[0].length === 2 ? ranges[0].slice(-1) : ranges[0]; + return [regexpEscape(r), false, endPos - pos, false]; + } + const sranges = "[" + (negate ? "^" : "") + rangesToString(ranges) + "]"; + const snegs = "[" + (negate ? "" : "^") + rangesToString(negs) + "]"; + const comb = ranges.length && negs.length ? "(" + sranges + "|" + snegs + ")" : ranges.length ? sranges : snegs; + return [comb, uflag, endPos - pos, true]; +}; + +// node_modules/minimatch/dist/esm/unescape.js +var unescape = (s, { windowsPathsNoEscape = false } = {}) => { + return windowsPathsNoEscape ? s.replace(/\[([^\/\\])\]/g, "$1") : s.replace(/((?!\\).|^)\[([^\/\\])\]/g, "$1$2").replace(/\\([^\/])/g, "$1"); +}; + +// node_modules/minimatch/dist/esm/ast.js +var types = /* @__PURE__ */ new Set(["!", "?", "+", "*", "@"]); +var isExtglobType = (c) => types.has(c); +var startNoTraversal = "(?!(?:^|/)\\.\\.?(?:$|/))"; +var startNoDot = "(?!\\.)"; +var addPatternStart = /* @__PURE__ */ new Set(["[", "."]); +var justDots = /* @__PURE__ */ new Set(["..", "."]); +var reSpecials = new Set("().*{}+?[]^$\\!"); +var regExpEscape = (s) => s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"); +var qmark = "[^/]"; +var star = qmark + "*?"; +var starNoEmpty = qmark + "+?"; +var AST = class _AST { + type; + #root; + #hasMagic; + #uflag = false; + #parts = []; + #parent; + #parentIndex; + #negs; + #filledNegs = false; + #options; + #toString; + // set to true if it's an extglob with no children + // (which really means one child of '') + #emptyExt = false; + constructor(type, parent, options = {}) { + this.type = type; + if (type) + this.#hasMagic = true; + this.#parent = parent; + this.#root = this.#parent ? this.#parent.#root : this; + this.#options = this.#root === this ? options : this.#root.#options; + this.#negs = this.#root === this ? [] : this.#root.#negs; + if (type === "!" && !this.#root.#filledNegs) + this.#negs.push(this); + this.#parentIndex = this.#parent ? this.#parent.#parts.length : 0; + } + get hasMagic() { + if (this.#hasMagic !== void 0) + return this.#hasMagic; + for (const p of this.#parts) { + if (typeof p === "string") + continue; + if (p.type || p.hasMagic) + return this.#hasMagic = true; + } + return this.#hasMagic; + } + // reconstructs the pattern + toString() { + if (this.#toString !== void 0) + return this.#toString; + if (!this.type) { + return this.#toString = this.#parts.map((p) => String(p)).join(""); + } else { + return this.#toString = this.type + "(" + this.#parts.map((p) => String(p)).join("|") + ")"; + } + } + #fillNegs() { + if (this !== this.#root) + throw new Error("should only call on root"); + if (this.#filledNegs) + return this; + this.toString(); + this.#filledNegs = true; + let n; + while (n = this.#negs.pop()) { + if (n.type !== "!") + continue; + let p = n; + let pp = p.#parent; + while (pp) { + for (let i = p.#parentIndex + 1; !pp.type && i < pp.#parts.length; i++) { + for (const part of n.#parts) { + if (typeof part === "string") { + throw new Error("string part in extglob AST??"); + } + part.copyIn(pp.#parts[i]); + } + } + p = pp; + pp = p.#parent; + } + } + return this; + } + push(...parts) { + for (const p of parts) { + if (p === "") + continue; + if (typeof p !== "string" && !(p instanceof _AST && p.#parent === this)) { + throw new Error("invalid part: " + p); + } + this.#parts.push(p); + } + } + toJSON() { + const ret = this.type === null ? this.#parts.slice().map((p) => typeof p === "string" ? p : p.toJSON()) : [this.type, ...this.#parts.map((p) => p.toJSON())]; + if (this.isStart() && !this.type) + ret.unshift([]); + if (this.isEnd() && (this === this.#root || this.#root.#filledNegs && this.#parent?.type === "!")) { + ret.push({}); + } + return ret; + } + isStart() { + if (this.#root === this) + return true; + if (!this.#parent?.isStart()) + return false; + if (this.#parentIndex === 0) + return true; + const p = this.#parent; + for (let i = 0; i < this.#parentIndex; i++) { + const pp = p.#parts[i]; + if (!(pp instanceof _AST && pp.type === "!")) { + return false; + } + } + return true; + } + isEnd() { + if (this.#root === this) + return true; + if (this.#parent?.type === "!") + return true; + if (!this.#parent?.isEnd()) + return false; + if (!this.type) + return this.#parent?.isEnd(); + const pl = this.#parent ? this.#parent.#parts.length : 0; + return this.#parentIndex === pl - 1; + } + copyIn(part) { + if (typeof part === "string") + this.push(part); + else + this.push(part.clone(this)); + } + clone(parent) { + const c = new _AST(this.type, parent); + for (const p of this.#parts) { + c.copyIn(p); + } + return c; + } + static #parseAST(str, ast, pos, opt) { + let escaping = false; + let inBrace = false; + let braceStart = -1; + let braceNeg = false; + if (ast.type === null) { + let i2 = pos; + let acc2 = ""; + while (i2 < str.length) { + const c = str.charAt(i2++); + if (escaping || c === "\\") { + escaping = !escaping; + acc2 += c; + continue; + } + if (inBrace) { + if (i2 === braceStart + 1) { + if (c === "^" || c === "!") { + braceNeg = true; + } + } else if (c === "]" && !(i2 === braceStart + 2 && braceNeg)) { + inBrace = false; + } + acc2 += c; + continue; + } else if (c === "[") { + inBrace = true; + braceStart = i2; + braceNeg = false; + acc2 += c; + continue; + } + if (!opt.noext && isExtglobType(c) && str.charAt(i2) === "(") { + ast.push(acc2); + acc2 = ""; + const ext2 = new _AST(c, ast); + i2 = _AST.#parseAST(str, ext2, i2, opt); + ast.push(ext2); + continue; + } + acc2 += c; + } + ast.push(acc2); + return i2; + } + let i = pos + 1; + let part = new _AST(null, ast); + const parts = []; + let acc = ""; + while (i < str.length) { + const c = str.charAt(i++); + if (escaping || c === "\\") { + escaping = !escaping; + acc += c; + continue; + } + if (inBrace) { + if (i === braceStart + 1) { + if (c === "^" || c === "!") { + braceNeg = true; + } + } else if (c === "]" && !(i === braceStart + 2 && braceNeg)) { + inBrace = false; + } + acc += c; + continue; + } else if (c === "[") { + inBrace = true; + braceStart = i; + braceNeg = false; + acc += c; + continue; + } + if (isExtglobType(c) && str.charAt(i) === "(") { + part.push(acc); + acc = ""; + const ext2 = new _AST(c, part); + part.push(ext2); + i = _AST.#parseAST(str, ext2, i, opt); + continue; + } + if (c === "|") { + part.push(acc); + acc = ""; + parts.push(part); + part = new _AST(null, ast); + continue; + } + if (c === ")") { + if (acc === "" && ast.#parts.length === 0) { + ast.#emptyExt = true; + } + part.push(acc); + acc = ""; + ast.push(...parts, part); + return i; + } + acc += c; + } + ast.type = null; + ast.#hasMagic = void 0; + ast.#parts = [str.substring(pos - 1)]; + return i; + } + static fromGlob(pattern, options = {}) { + const ast = new _AST(null, void 0, options); + _AST.#parseAST(pattern, ast, 0, options); + return ast; + } + // returns the regular expression if there's magic, or the unescaped + // string if not. + toMMPattern() { + if (this !== this.#root) + return this.#root.toMMPattern(); + const glob2 = this.toString(); + const [re, body, hasMagic2, uflag] = this.toRegExpSource(); + const anyMagic = hasMagic2 || this.#hasMagic || this.#options.nocase && !this.#options.nocaseMagicOnly && glob2.toUpperCase() !== glob2.toLowerCase(); + if (!anyMagic) { + return body; + } + const flags = (this.#options.nocase ? "i" : "") + (uflag ? "u" : ""); + return Object.assign(new RegExp(`^${re}$`, flags), { + _src: re, + _glob: glob2 + }); + } + get options() { + return this.#options; + } + // returns the string match, the regexp source, whether there's magic + // in the regexp (so a regular expression is required) and whether or + // not the uflag is needed for the regular expression (for posix classes) + // TODO: instead of injecting the start/end at this point, just return + // the BODY of the regexp, along with the start/end portions suitable + // for binding the start/end in either a joined full-path makeRe context + // (where we bind to (^|/), or a standalone matchPart context (where + // we bind to ^, and not /). Otherwise slashes get duped! + // + // In part-matching mode, the start is: + // - if not isStart: nothing + // - if traversal possible, but not allowed: ^(?!\.\.?$) + // - if dots allowed or not possible: ^ + // - if dots possible and not allowed: ^(?!\.) + // end is: + // - if not isEnd(): nothing + // - else: $ + // + // In full-path matching mode, we put the slash at the START of the + // pattern, so start is: + // - if first pattern: same as part-matching mode + // - if not isStart(): nothing + // - if traversal possible, but not allowed: /(?!\.\.?(?:$|/)) + // - if dots allowed or not possible: / + // - if dots possible and not allowed: /(?!\.) + // end is: + // - if last pattern, same as part-matching mode + // - else nothing + // + // Always put the (?:$|/) on negated tails, though, because that has to be + // there to bind the end of the negated pattern portion, and it's easier to + // just stick it in now rather than try to inject it later in the middle of + // the pattern. + // + // We can just always return the same end, and leave it up to the caller + // to know whether it's going to be used joined or in parts. + // And, if the start is adjusted slightly, can do the same there: + // - if not isStart: nothing + // - if traversal possible, but not allowed: (?:/|^)(?!\.\.?$) + // - if dots allowed or not possible: (?:/|^) + // - if dots possible and not allowed: (?:/|^)(?!\.) + // + // But it's better to have a simpler binding without a conditional, for + // performance, so probably better to return both start options. + // + // Then the caller just ignores the end if it's not the first pattern, + // and the start always gets applied. + // + // But that's always going to be $ if it's the ending pattern, or nothing, + // so the caller can just attach $ at the end of the pattern when building. + // + // So the todo is: + // - better detect what kind of start is needed + // - return both flavors of starting pattern + // - attach $ at the end of the pattern when creating the actual RegExp + // + // Ah, but wait, no, that all only applies to the root when the first pattern + // is not an extglob. If the first pattern IS an extglob, then we need all + // that dot prevention biz to live in the extglob portions, because eg + // +(*|.x*) can match .xy but not .yx. + // + // So, return the two flavors if it's #root and the first child is not an + // AST, otherwise leave it to the child AST to handle it, and there, + // use the (?:^|/) style of start binding. + // + // Even simplified further: + // - Since the start for a join is eg /(?!\.) and the start for a part + // is ^(?!\.), we can just prepend (?!\.) to the pattern (either root + // or start or whatever) and prepend ^ or / at the Regexp construction. + toRegExpSource(allowDot) { + const dot = allowDot ?? !!this.#options.dot; + if (this.#root === this) + this.#fillNegs(); + if (!this.type) { + const noEmpty = this.isStart() && this.isEnd(); + const src = this.#parts.map((p) => { + const [re, _, hasMagic2, uflag] = typeof p === "string" ? _AST.#parseGlob(p, this.#hasMagic, noEmpty) : p.toRegExpSource(allowDot); + this.#hasMagic = this.#hasMagic || hasMagic2; + this.#uflag = this.#uflag || uflag; + return re; + }).join(""); + let start2 = ""; + if (this.isStart()) { + if (typeof this.#parts[0] === "string") { + const dotTravAllowed = this.#parts.length === 1 && justDots.has(this.#parts[0]); + if (!dotTravAllowed) { + const aps = addPatternStart; + const needNoTrav = ( + // dots are allowed, and the pattern starts with [ or . + dot && aps.has(src.charAt(0)) || // the pattern starts with \., and then [ or . + src.startsWith("\\.") && aps.has(src.charAt(2)) || // the pattern starts with \.\., and then [ or . + src.startsWith("\\.\\.") && aps.has(src.charAt(4)) + ); + const needNoDot = !dot && !allowDot && aps.has(src.charAt(0)); + start2 = needNoTrav ? startNoTraversal : needNoDot ? startNoDot : ""; + } + } + } + let end = ""; + if (this.isEnd() && this.#root.#filledNegs && this.#parent?.type === "!") { + end = "(?:$|\\/)"; + } + const final2 = start2 + src + end; + return [ + final2, + unescape(src), + this.#hasMagic = !!this.#hasMagic, + this.#uflag + ]; + } + const repeated = this.type === "*" || this.type === "+"; + const start = this.type === "!" ? "(?:(?!(?:" : "(?:"; + let body = this.#partsToRegExp(dot); + if (this.isStart() && this.isEnd() && !body && this.type !== "!") { + const s = this.toString(); + this.#parts = [s]; + this.type = null; + this.#hasMagic = void 0; + return [s, unescape(this.toString()), false, false]; + } + let bodyDotAllowed = !repeated || allowDot || dot || !startNoDot ? "" : this.#partsToRegExp(true); + if (bodyDotAllowed === body) { + bodyDotAllowed = ""; + } + if (bodyDotAllowed) { + body = `(?:${body})(?:${bodyDotAllowed})*?`; + } + let final = ""; + if (this.type === "!" && this.#emptyExt) { + final = (this.isStart() && !dot ? startNoDot : "") + starNoEmpty; + } else { + const close = this.type === "!" ? ( + // !() must match something,but !(x) can match '' + "))" + (this.isStart() && !dot && !allowDot ? startNoDot : "") + star + ")" + ) : this.type === "@" ? ")" : this.type === "?" ? ")?" : this.type === "+" && bodyDotAllowed ? ")" : this.type === "*" && bodyDotAllowed ? `)?` : `)${this.type}`; + final = start + body + close; + } + return [ + final, + unescape(body), + this.#hasMagic = !!this.#hasMagic, + this.#uflag + ]; + } + #partsToRegExp(dot) { + return this.#parts.map((p) => { + if (typeof p === "string") { + throw new Error("string type in extglob ast??"); + } + const [re, _, _hasMagic, uflag] = p.toRegExpSource(dot); + this.#uflag = this.#uflag || uflag; + return re; + }).filter((p) => !(this.isStart() && this.isEnd()) || !!p).join("|"); + } + static #parseGlob(glob2, hasMagic2, noEmpty = false) { + let escaping = false; + let re = ""; + let uflag = false; + for (let i = 0; i < glob2.length; i++) { + const c = glob2.charAt(i); + if (escaping) { + escaping = false; + re += (reSpecials.has(c) ? "\\" : "") + c; + continue; + } + if (c === "\\") { + if (i === glob2.length - 1) { + re += "\\\\"; + } else { + escaping = true; + } + continue; + } + if (c === "[") { + const [src, needUflag, consumed, magic] = parseClass(glob2, i); + if (consumed) { + re += src; + uflag = uflag || needUflag; + i += consumed - 1; + hasMagic2 = hasMagic2 || magic; + continue; + } + } + if (c === "*") { + if (noEmpty && glob2 === "*") + re += starNoEmpty; + else + re += star; + hasMagic2 = true; + continue; + } + if (c === "?") { + re += qmark; + hasMagic2 = true; + continue; + } + re += regExpEscape(c); + } + return [re, unescape(glob2), !!hasMagic2, uflag]; + } +}; + +// node_modules/minimatch/dist/esm/escape.js +var escape = (s, { windowsPathsNoEscape = false } = {}) => { + return windowsPathsNoEscape ? s.replace(/[?*()[\]]/g, "[$&]") : s.replace(/[?*()[\]\\]/g, "\\$&"); +}; + +// node_modules/minimatch/dist/esm/index.js +var minimatch = (p, pattern, options = {}) => { + assertValidPattern(pattern); + if (!options.nocomment && pattern.charAt(0) === "#") { + return false; + } + return new Minimatch(pattern, options).match(p); +}; +var starDotExtRE = /^\*+([^+@!?\*\[\(]*)$/; +var starDotExtTest = (ext2) => (f) => !f.startsWith(".") && f.endsWith(ext2); +var starDotExtTestDot = (ext2) => (f) => f.endsWith(ext2); +var starDotExtTestNocase = (ext2) => { + ext2 = ext2.toLowerCase(); + return (f) => !f.startsWith(".") && f.toLowerCase().endsWith(ext2); +}; +var starDotExtTestNocaseDot = (ext2) => { + ext2 = ext2.toLowerCase(); + return (f) => f.toLowerCase().endsWith(ext2); +}; +var starDotStarRE = /^\*+\.\*+$/; +var starDotStarTest = (f) => !f.startsWith(".") && f.includes("."); +var starDotStarTestDot = (f) => f !== "." && f !== ".." && f.includes("."); +var dotStarRE = /^\.\*+$/; +var dotStarTest = (f) => f !== "." && f !== ".." && f.startsWith("."); +var starRE = /^\*+$/; +var starTest = (f) => f.length !== 0 && !f.startsWith("."); +var starTestDot = (f) => f.length !== 0 && f !== "." && f !== ".."; +var qmarksRE = /^\?+([^+@!?\*\[\(]*)?$/; +var qmarksTestNocase = ([$0, ext2 = ""]) => { + const noext = qmarksTestNoExt([$0]); + if (!ext2) + return noext; + ext2 = ext2.toLowerCase(); + return (f) => noext(f) && f.toLowerCase().endsWith(ext2); +}; +var qmarksTestNocaseDot = ([$0, ext2 = ""]) => { + const noext = qmarksTestNoExtDot([$0]); + if (!ext2) + return noext; + ext2 = ext2.toLowerCase(); + return (f) => noext(f) && f.toLowerCase().endsWith(ext2); +}; +var qmarksTestDot = ([$0, ext2 = ""]) => { + const noext = qmarksTestNoExtDot([$0]); + return !ext2 ? noext : (f) => noext(f) && f.endsWith(ext2); +}; +var qmarksTest = ([$0, ext2 = ""]) => { + const noext = qmarksTestNoExt([$0]); + return !ext2 ? noext : (f) => noext(f) && f.endsWith(ext2); +}; +var qmarksTestNoExt = ([$0]) => { + const len = $0.length; + return (f) => f.length === len && !f.startsWith("."); +}; +var qmarksTestNoExtDot = ([$0]) => { + const len = $0.length; + return (f) => f.length === len && f !== "." && f !== ".."; +}; +var defaultPlatform = typeof process === "object" && process ? typeof process.env === "object" && process.env && process.env.__MINIMATCH_TESTING_PLATFORM__ || process.platform : "posix"; +var path = { + win32: { sep: "\\" }, + posix: { sep: "/" } +}; +var sep = defaultPlatform === "win32" ? path.win32.sep : path.posix.sep; +minimatch.sep = sep; +var GLOBSTAR = Symbol("globstar **"); +minimatch.GLOBSTAR = GLOBSTAR; +var qmark2 = "[^/]"; +var star2 = qmark2 + "*?"; +var twoStarDot = "(?:(?!(?:\\/|^)(?:\\.{1,2})($|\\/)).)*?"; +var twoStarNoDot = "(?:(?!(?:\\/|^)\\.).)*?"; +var filter = (pattern, options = {}) => (p) => minimatch(p, pattern, options); +minimatch.filter = filter; +var ext = (a, b = {}) => Object.assign({}, a, b); +var defaults = (def) => { + if (!def || typeof def !== "object" || !Object.keys(def).length) { + return minimatch; + } + const orig = minimatch; + const m = (p, pattern, options = {}) => orig(p, pattern, ext(def, options)); + return Object.assign(m, { + Minimatch: class Minimatch extends orig.Minimatch { + constructor(pattern, options = {}) { + super(pattern, ext(def, options)); + } + static defaults(options) { + return orig.defaults(ext(def, options)).Minimatch; + } + }, + AST: class AST extends orig.AST { + /* c8 ignore start */ + constructor(type, parent, options = {}) { + super(type, parent, ext(def, options)); + } + /* c8 ignore stop */ + static fromGlob(pattern, options = {}) { + return orig.AST.fromGlob(pattern, ext(def, options)); + } + }, + unescape: (s, options = {}) => orig.unescape(s, ext(def, options)), + escape: (s, options = {}) => orig.escape(s, ext(def, options)), + filter: (pattern, options = {}) => orig.filter(pattern, ext(def, options)), + defaults: (options) => orig.defaults(ext(def, options)), + makeRe: (pattern, options = {}) => orig.makeRe(pattern, ext(def, options)), + braceExpand: (pattern, options = {}) => orig.braceExpand(pattern, ext(def, options)), + match: (list, pattern, options = {}) => orig.match(list, pattern, ext(def, options)), + sep: orig.sep, + GLOBSTAR + }); +}; +minimatch.defaults = defaults; +var braceExpand = (pattern, options = {}) => { + assertValidPattern(pattern); + if (options.nobrace || !/\{(?:(?!\{).)*\}/.test(pattern)) { + return [pattern]; + } + return (0, import_brace_expansion.default)(pattern); +}; +minimatch.braceExpand = braceExpand; +var makeRe = (pattern, options = {}) => new Minimatch(pattern, options).makeRe(); +minimatch.makeRe = makeRe; +var match = (list, pattern, options = {}) => { + const mm = new Minimatch(pattern, options); + list = list.filter((f) => mm.match(f)); + if (mm.options.nonull && !list.length) { + list.push(pattern); + } + return list; +}; +minimatch.match = match; +var globMagic = /[?*]|[+@!]\(.*?\)|\[|\]/; +var regExpEscape2 = (s) => s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"); +var Minimatch = class { + options; + set; + pattern; + windowsPathsNoEscape; + nonegate; + negate; + comment; + empty; + preserveMultipleSlashes; + partial; + globSet; + globParts; + nocase; + isWindows; + platform; + windowsNoMagicRoot; + regexp; + constructor(pattern, options = {}) { + assertValidPattern(pattern); + options = options || {}; + this.options = options; + this.pattern = pattern; + this.platform = options.platform || defaultPlatform; + this.isWindows = this.platform === "win32"; + this.windowsPathsNoEscape = !!options.windowsPathsNoEscape || options.allowWindowsEscape === false; + if (this.windowsPathsNoEscape) { + this.pattern = this.pattern.replace(/\\/g, "/"); + } + this.preserveMultipleSlashes = !!options.preserveMultipleSlashes; + this.regexp = null; + this.negate = false; + this.nonegate = !!options.nonegate; + this.comment = false; + this.empty = false; + this.partial = !!options.partial; + this.nocase = !!this.options.nocase; + this.windowsNoMagicRoot = options.windowsNoMagicRoot !== void 0 ? options.windowsNoMagicRoot : !!(this.isWindows && this.nocase); + this.globSet = []; + this.globParts = []; + this.set = []; + this.make(); + } + hasMagic() { + if (this.options.magicalBraces && this.set.length > 1) { + return true; + } + for (const pattern of this.set) { + for (const part of pattern) { + if (typeof part !== "string") + return true; + } + } + return false; + } + debug(..._) { + } + make() { + const pattern = this.pattern; + const options = this.options; + if (!options.nocomment && pattern.charAt(0) === "#") { + this.comment = true; + return; + } + if (!pattern) { + this.empty = true; + return; + } + this.parseNegate(); + this.globSet = [...new Set(this.braceExpand())]; + if (options.debug) { + this.debug = (...args) => console.error(...args); + } + this.debug(this.pattern, this.globSet); + const rawGlobParts = this.globSet.map((s) => this.slashSplit(s)); + this.globParts = this.preprocess(rawGlobParts); + this.debug(this.pattern, this.globParts); + let set = this.globParts.map((s, _, __) => { + if (this.isWindows && this.windowsNoMagicRoot) { + const isUNC = s[0] === "" && s[1] === "" && (s[2] === "?" || !globMagic.test(s[2])) && !globMagic.test(s[3]); + const isDrive = /^[a-z]:/i.test(s[0]); + if (isUNC) { + return [...s.slice(0, 4), ...s.slice(4).map((ss) => this.parse(ss))]; + } else if (isDrive) { + return [s[0], ...s.slice(1).map((ss) => this.parse(ss))]; + } + } + return s.map((ss) => this.parse(ss)); + }); + this.debug(this.pattern, set); + this.set = set.filter((s) => s.indexOf(false) === -1); + if (this.isWindows) { + for (let i = 0; i < this.set.length; i++) { + const p = this.set[i]; + if (p[0] === "" && p[1] === "" && this.globParts[i][2] === "?" && typeof p[3] === "string" && /^[a-z]:$/i.test(p[3])) { + p[2] = "?"; + } + } + } + this.debug(this.pattern, this.set); + } + // various transforms to equivalent pattern sets that are + // faster to process in a filesystem walk. The goal is to + // eliminate what we can, and push all ** patterns as far + // to the right as possible, even if it increases the number + // of patterns that we have to process. + preprocess(globParts) { + if (this.options.noglobstar) { + for (let i = 0; i < globParts.length; i++) { + for (let j = 0; j < globParts[i].length; j++) { + if (globParts[i][j] === "**") { + globParts[i][j] = "*"; + } + } + } + } + const { optimizationLevel = 1 } = this.options; + if (optimizationLevel >= 2) { + globParts = this.firstPhasePreProcess(globParts); + globParts = this.secondPhasePreProcess(globParts); + } else if (optimizationLevel >= 1) { + globParts = this.levelOneOptimize(globParts); + } else { + globParts = this.adjascentGlobstarOptimize(globParts); + } + return globParts; + } + // just get rid of adjascent ** portions + adjascentGlobstarOptimize(globParts) { + return globParts.map((parts) => { + let gs = -1; + while (-1 !== (gs = parts.indexOf("**", gs + 1))) { + let i = gs; + while (parts[i + 1] === "**") { + i++; + } + if (i !== gs) { + parts.splice(gs, i - gs); + } + } + return parts; + }); + } + // get rid of adjascent ** and resolve .. portions + levelOneOptimize(globParts) { + return globParts.map((parts) => { + parts = parts.reduce((set, part) => { + const prev = set[set.length - 1]; + if (part === "**" && prev === "**") { + return set; + } + if (part === "..") { + if (prev && prev !== ".." && prev !== "." && prev !== "**") { + set.pop(); + return set; + } + } + set.push(part); + return set; + }, []); + return parts.length === 0 ? [""] : parts; + }); + } + levelTwoFileOptimize(parts) { + if (!Array.isArray(parts)) { + parts = this.slashSplit(parts); + } + let didSomething = false; + do { + didSomething = false; + if (!this.preserveMultipleSlashes) { + for (let i = 1; i < parts.length - 1; i++) { + const p = parts[i]; + if (i === 1 && p === "" && parts[0] === "") + continue; + if (p === "." || p === "") { + didSomething = true; + parts.splice(i, 1); + i--; + } + } + if (parts[0] === "." && parts.length === 2 && (parts[1] === "." || parts[1] === "")) { + didSomething = true; + parts.pop(); + } + } + let dd = 0; + while (-1 !== (dd = parts.indexOf("..", dd + 1))) { + const p = parts[dd - 1]; + if (p && p !== "." && p !== ".." && p !== "**") { + didSomething = true; + parts.splice(dd - 1, 2); + dd -= 2; + } + } + } while (didSomething); + return parts.length === 0 ? [""] : parts; + } + // First phase: single-pattern processing + //
 is 1 or more portions
+  //  is 1 or more portions
+  // 

is any portion other than ., .., '', or ** + // is . or '' + // + // **/.. is *brutal* for filesystem walking performance, because + // it effectively resets the recursive walk each time it occurs, + // and ** cannot be reduced out by a .. pattern part like a regexp + // or most strings (other than .., ., and '') can be. + // + //

/**/../

/

/ -> {

/../

/

/,

/**/

/

/} + //

// -> 
/
+  // 
/

/../ ->

/
+  // **/**/ -> **/
+  //
+  // **/*/ -> */**/ <== not valid because ** doesn't follow
+  // this WOULD be allowed if ** did follow symlinks, or * didn't
+  firstPhasePreProcess(globParts) {
+    let didSomething = false;
+    do {
+      didSomething = false;
+      for (let parts of globParts) {
+        let gs = -1;
+        while (-1 !== (gs = parts.indexOf("**", gs + 1))) {
+          let gss = gs;
+          while (parts[gss + 1] === "**") {
+            gss++;
+          }
+          if (gss > gs) {
+            parts.splice(gs + 1, gss - gs);
+          }
+          let next = parts[gs + 1];
+          const p = parts[gs + 2];
+          const p2 = parts[gs + 3];
+          if (next !== "..")
+            continue;
+          if (!p || p === "." || p === ".." || !p2 || p2 === "." || p2 === "..") {
+            continue;
+          }
+          didSomething = true;
+          parts.splice(gs, 1);
+          const other = parts.slice(0);
+          other[gs] = "**";
+          globParts.push(other);
+          gs--;
+        }
+        if (!this.preserveMultipleSlashes) {
+          for (let i = 1; i < parts.length - 1; i++) {
+            const p = parts[i];
+            if (i === 1 && p === "" && parts[0] === "")
+              continue;
+            if (p === "." || p === "") {
+              didSomething = true;
+              parts.splice(i, 1);
+              i--;
+            }
+          }
+          if (parts[0] === "." && parts.length === 2 && (parts[1] === "." || parts[1] === "")) {
+            didSomething = true;
+            parts.pop();
+          }
+        }
+        let dd = 0;
+        while (-1 !== (dd = parts.indexOf("..", dd + 1))) {
+          const p = parts[dd - 1];
+          if (p && p !== "." && p !== ".." && p !== "**") {
+            didSomething = true;
+            const needDot = dd === 1 && parts[dd + 1] === "**";
+            const splin = needDot ? ["."] : [];
+            parts.splice(dd - 1, 2, ...splin);
+            if (parts.length === 0)
+              parts.push("");
+            dd -= 2;
+          }
+        }
+      }
+    } while (didSomething);
+    return globParts;
+  }
+  // second phase: multi-pattern dedupes
+  // {
/*/,
/

/} ->

/*/
+  // {
/,
/} -> 
/
+  // {
/**/,
/} -> 
/**/
+  //
+  // {
/**/,
/**/

/} ->

/**/
+  // ^-- not valid because ** doens't follow symlinks
+  secondPhasePreProcess(globParts) {
+    for (let i = 0; i < globParts.length - 1; i++) {
+      for (let j = i + 1; j < globParts.length; j++) {
+        const matched = this.partsMatch(globParts[i], globParts[j], !this.preserveMultipleSlashes);
+        if (!matched)
+          continue;
+        globParts[i] = matched;
+        globParts[j] = [];
+      }
+    }
+    return globParts.filter((gs) => gs.length);
+  }
+  partsMatch(a, b, emptyGSMatch = false) {
+    let ai = 0;
+    let bi = 0;
+    let result = [];
+    let which = "";
+    while (ai < a.length && bi < b.length) {
+      if (a[ai] === b[bi]) {
+        result.push(which === "b" ? b[bi] : a[ai]);
+        ai++;
+        bi++;
+      } else if (emptyGSMatch && a[ai] === "**" && b[bi] === a[ai + 1]) {
+        result.push(a[ai]);
+        ai++;
+      } else if (emptyGSMatch && b[bi] === "**" && a[ai] === b[bi + 1]) {
+        result.push(b[bi]);
+        bi++;
+      } else if (a[ai] === "*" && b[bi] && (this.options.dot || !b[bi].startsWith(".")) && b[bi] !== "**") {
+        if (which === "b")
+          return false;
+        which = "a";
+        result.push(a[ai]);
+        ai++;
+        bi++;
+      } else if (b[bi] === "*" && a[ai] && (this.options.dot || !a[ai].startsWith(".")) && a[ai] !== "**") {
+        if (which === "a")
+          return false;
+        which = "b";
+        result.push(b[bi]);
+        ai++;
+        bi++;
+      } else {
+        return false;
+      }
+    }
+    return a.length === b.length && result;
+  }
+  parseNegate() {
+    if (this.nonegate)
+      return;
+    const pattern = this.pattern;
+    let negate = false;
+    let negateOffset = 0;
+    for (let i = 0; i < pattern.length && pattern.charAt(i) === "!"; i++) {
+      negate = !negate;
+      negateOffset++;
+    }
+    if (negateOffset)
+      this.pattern = pattern.slice(negateOffset);
+    this.negate = negate;
+  }
+  // set partial to true to test if, for example,
+  // "/a/b" matches the start of "/*/b/*/d"
+  // Partial means, if you run out of file before you run
+  // out of pattern, then that's fine, as long as all
+  // the parts match.
+  matchOne(file, pattern, partial = false) {
+    const options = this.options;
+    if (this.isWindows) {
+      const fileDrive = typeof file[0] === "string" && /^[a-z]:$/i.test(file[0]);
+      const fileUNC = !fileDrive && file[0] === "" && file[1] === "" && file[2] === "?" && /^[a-z]:$/i.test(file[3]);
+      const patternDrive = typeof pattern[0] === "string" && /^[a-z]:$/i.test(pattern[0]);
+      const patternUNC = !patternDrive && pattern[0] === "" && pattern[1] === "" && pattern[2] === "?" && typeof pattern[3] === "string" && /^[a-z]:$/i.test(pattern[3]);
+      const fdi = fileUNC ? 3 : fileDrive ? 0 : void 0;
+      const pdi = patternUNC ? 3 : patternDrive ? 0 : void 0;
+      if (typeof fdi === "number" && typeof pdi === "number") {
+        const [fd, pd] = [file[fdi], pattern[pdi]];
+        if (fd.toLowerCase() === pd.toLowerCase()) {
+          pattern[pdi] = fd;
+          if (pdi > fdi) {
+            pattern = pattern.slice(pdi);
+          } else if (fdi > pdi) {
+            file = file.slice(fdi);
+          }
+        }
+      }
+    }
+    const { optimizationLevel = 1 } = this.options;
+    if (optimizationLevel >= 2) {
+      file = this.levelTwoFileOptimize(file);
+    }
+    this.debug("matchOne", this, { file, pattern });
+    this.debug("matchOne", file.length, pattern.length);
+    for (var fi = 0, pi = 0, fl = file.length, pl = pattern.length; fi < fl && pi < pl; fi++, pi++) {
+      this.debug("matchOne loop");
+      var p = pattern[pi];
+      var f = file[fi];
+      this.debug(pattern, p, f);
+      if (p === false) {
+        return false;
+      }
+      if (p === GLOBSTAR) {
+        this.debug("GLOBSTAR", [pattern, p, f]);
+        var fr = fi;
+        var pr = pi + 1;
+        if (pr === pl) {
+          this.debug("** at the end");
+          for (; fi < fl; fi++) {
+            if (file[fi] === "." || file[fi] === ".." || !options.dot && file[fi].charAt(0) === ".")
+              return false;
+          }
+          return true;
+        }
+        while (fr < fl) {
+          var swallowee = file[fr];
+          this.debug("\nglobstar while", file, fr, pattern, pr, swallowee);
+          if (this.matchOne(file.slice(fr), pattern.slice(pr), partial)) {
+            this.debug("globstar found match!", fr, fl, swallowee);
+            return true;
+          } else {
+            if (swallowee === "." || swallowee === ".." || !options.dot && swallowee.charAt(0) === ".") {
+              this.debug("dot detected!", file, fr, pattern, pr);
+              break;
+            }
+            this.debug("globstar swallow a segment, and continue");
+            fr++;
+          }
+        }
+        if (partial) {
+          this.debug("\n>>> no match, partial?", file, fr, pattern, pr);
+          if (fr === fl) {
+            return true;
+          }
+        }
+        return false;
+      }
+      let hit;
+      if (typeof p === "string") {
+        hit = f === p;
+        this.debug("string match", p, f, hit);
+      } else {
+        hit = p.test(f);
+        this.debug("pattern match", p, f, hit);
+      }
+      if (!hit)
+        return false;
+    }
+    if (fi === fl && pi === pl) {
+      return true;
+    } else if (fi === fl) {
+      return partial;
+    } else if (pi === pl) {
+      return fi === fl - 1 && file[fi] === "";
+    } else {
+      throw new Error("wtf?");
+    }
+  }
+  braceExpand() {
+    return braceExpand(this.pattern, this.options);
+  }
+  parse(pattern) {
+    assertValidPattern(pattern);
+    const options = this.options;
+    if (pattern === "**")
+      return GLOBSTAR;
+    if (pattern === "")
+      return "";
+    let m;
+    let fastTest = null;
+    if (m = pattern.match(starRE)) {
+      fastTest = options.dot ? starTestDot : starTest;
+    } else if (m = pattern.match(starDotExtRE)) {
+      fastTest = (options.nocase ? options.dot ? starDotExtTestNocaseDot : starDotExtTestNocase : options.dot ? starDotExtTestDot : starDotExtTest)(m[1]);
+    } else if (m = pattern.match(qmarksRE)) {
+      fastTest = (options.nocase ? options.dot ? qmarksTestNocaseDot : qmarksTestNocase : options.dot ? qmarksTestDot : qmarksTest)(m);
+    } else if (m = pattern.match(starDotStarRE)) {
+      fastTest = options.dot ? starDotStarTestDot : starDotStarTest;
+    } else if (m = pattern.match(dotStarRE)) {
+      fastTest = dotStarTest;
+    }
+    const re = AST.fromGlob(pattern, this.options).toMMPattern();
+    if (fastTest && typeof re === "object") {
+      Reflect.defineProperty(re, "test", { value: fastTest });
+    }
+    return re;
+  }
+  makeRe() {
+    if (this.regexp || this.regexp === false)
+      return this.regexp;
+    const set = this.set;
+    if (!set.length) {
+      this.regexp = false;
+      return this.regexp;
+    }
+    const options = this.options;
+    const twoStar = options.noglobstar ? star2 : options.dot ? twoStarDot : twoStarNoDot;
+    const flags = new Set(options.nocase ? ["i"] : []);
+    let re = set.map((pattern) => {
+      const pp = pattern.map((p) => {
+        if (p instanceof RegExp) {
+          for (const f of p.flags.split(""))
+            flags.add(f);
+        }
+        return typeof p === "string" ? regExpEscape2(p) : p === GLOBSTAR ? GLOBSTAR : p._src;
+      });
+      pp.forEach((p, i) => {
+        const next = pp[i + 1];
+        const prev = pp[i - 1];
+        if (p !== GLOBSTAR || prev === GLOBSTAR) {
+          return;
+        }
+        if (prev === void 0) {
+          if (next !== void 0 && next !== GLOBSTAR) {
+            pp[i + 1] = "(?:\\/|" + twoStar + "\\/)?" + next;
+          } else {
+            pp[i] = twoStar;
+          }
+        } else if (next === void 0) {
+          pp[i - 1] = prev + "(?:\\/|" + twoStar + ")?";
+        } else if (next !== GLOBSTAR) {
+          pp[i - 1] = prev + "(?:\\/|\\/" + twoStar + "\\/)" + next;
+          pp[i + 1] = GLOBSTAR;
+        }
+      });
+      return pp.filter((p) => p !== GLOBSTAR).join("/");
+    }).join("|");
+    const [open, close] = set.length > 1 ? ["(?:", ")"] : ["", ""];
+    re = "^" + open + re + close + "$";
+    if (this.negate)
+      re = "^(?!" + re + ").+$";
+    try {
+      this.regexp = new RegExp(re, [...flags].join(""));
+    } catch (ex) {
+      this.regexp = false;
+    }
+    return this.regexp;
+  }
+  slashSplit(p) {
+    if (this.preserveMultipleSlashes) {
+      return p.split("/");
+    } else if (this.isWindows && /^\/\/[^\/]+/.test(p)) {
+      return ["", ...p.split(/\/+/)];
+    } else {
+      return p.split(/\/+/);
+    }
+  }
+  match(f, partial = this.partial) {
+    this.debug("match", f, this.pattern);
+    if (this.comment) {
+      return false;
+    }
+    if (this.empty) {
+      return f === "";
+    }
+    if (f === "/" && partial) {
+      return true;
+    }
+    const options = this.options;
+    if (this.isWindows) {
+      f = f.split("\\").join("/");
+    }
+    const ff = this.slashSplit(f);
+    this.debug(this.pattern, "split", ff);
+    const set = this.set;
+    this.debug(this.pattern, "set", set);
+    let filename = ff[ff.length - 1];
+    if (!filename) {
+      for (let i = ff.length - 2; !filename && i >= 0; i--) {
+        filename = ff[i];
+      }
+    }
+    for (let i = 0; i < set.length; i++) {
+      const pattern = set[i];
+      let file = ff;
+      if (options.matchBase && pattern.length === 1) {
+        file = [filename];
+      }
+      const hit = this.matchOne(file, pattern, partial);
+      if (hit) {
+        if (options.flipNegate) {
+          return true;
+        }
+        return !this.negate;
+      }
+    }
+    if (options.flipNegate) {
+      return false;
+    }
+    return this.negate;
+  }
+  static defaults(def) {
+    return minimatch.defaults(def).Minimatch;
+  }
+};
+minimatch.AST = AST;
+minimatch.Minimatch = Minimatch;
+minimatch.escape = escape;
+minimatch.unescape = unescape;
+
+// node_modules/lru-cache/dist/esm/index.js
+var perf = typeof performance === "object" && performance && typeof performance.now === "function" ? performance : Date;
+var warned = /* @__PURE__ */ new Set();
+var PROCESS = typeof process === "object" && !!process ? process : {};
+var emitWarning = (msg, type, code, fn) => {
+  typeof PROCESS.emitWarning === "function" ? PROCESS.emitWarning(msg, type, code, fn) : console.error(`[${code}] ${type}: ${msg}`);
+};
+var AC = globalThis.AbortController;
+var AS = globalThis.AbortSignal;
+if (typeof AC === "undefined") {
+  AS = class AbortSignal {
+    onabort;
+    _onabort = [];
+    reason;
+    aborted = false;
+    addEventListener(_, fn) {
+      this._onabort.push(fn);
+    }
+  };
+  AC = class AbortController {
+    constructor() {
+      warnACPolyfill();
+    }
+    signal = new AS();
+    abort(reason) {
+      if (this.signal.aborted)
+        return;
+      this.signal.reason = reason;
+      this.signal.aborted = true;
+      for (const fn of this.signal._onabort) {
+        fn(reason);
+      }
+      this.signal.onabort?.(reason);
+    }
+  };
+  let printACPolyfillWarning = PROCESS.env?.LRU_CACHE_IGNORE_AC_WARNING !== "1";
+  const warnACPolyfill = () => {
+    if (!printACPolyfillWarning)
+      return;
+    printACPolyfillWarning = false;
+    emitWarning("AbortController is not defined. If using lru-cache in node 14, load an AbortController polyfill from the `node-abort-controller` package. A minimal polyfill is provided for use by LRUCache.fetch(), but it should not be relied upon in other contexts (eg, passing it to other APIs that use AbortController/AbortSignal might have undesirable effects). You may disable this with LRU_CACHE_IGNORE_AC_WARNING=1 in the env.", "NO_ABORT_CONTROLLER", "ENOTSUP", warnACPolyfill);
+  };
+}
+var shouldWarn = (code) => !warned.has(code);
+var TYPE = Symbol("type");
+var isPosInt = (n) => n && n === Math.floor(n) && n > 0 && isFinite(n);
+var getUintArray = (max) => !isPosInt(max) ? null : max <= Math.pow(2, 8) ? Uint8Array : max <= Math.pow(2, 16) ? Uint16Array : max <= Math.pow(2, 32) ? Uint32Array : max <= Number.MAX_SAFE_INTEGER ? ZeroArray : null;
+var ZeroArray = class extends Array {
+  constructor(size) {
+    super(size);
+    this.fill(0);
+  }
+};
+var Stack = class _Stack {
+  heap;
+  length;
+  // private constructor
+  static #constructing = false;
+  static create(max) {
+    const HeapCls = getUintArray(max);
+    if (!HeapCls)
+      return [];
+    _Stack.#constructing = true;
+    const s = new _Stack(max, HeapCls);
+    _Stack.#constructing = false;
+    return s;
+  }
+  constructor(max, HeapCls) {
+    if (!_Stack.#constructing) {
+      throw new TypeError("instantiate Stack using Stack.create(n)");
+    }
+    this.heap = new HeapCls(max);
+    this.length = 0;
+  }
+  push(n) {
+    this.heap[this.length++] = n;
+  }
+  pop() {
+    return this.heap[--this.length];
+  }
+};
+var LRUCache = class _LRUCache {
+  // properties coming in from the options of these, only max and maxSize
+  // really *need* to be protected. The rest can be modified, as they just
+  // set defaults for various methods.
+  #max;
+  #maxSize;
+  #dispose;
+  #disposeAfter;
+  #fetchMethod;
+  /**
+   * {@link LRUCache.OptionsBase.ttl}
+   */
+  ttl;
+  /**
+   * {@link LRUCache.OptionsBase.ttlResolution}
+   */
+  ttlResolution;
+  /**
+   * {@link LRUCache.OptionsBase.ttlAutopurge}
+   */
+  ttlAutopurge;
+  /**
+   * {@link LRUCache.OptionsBase.updateAgeOnGet}
+   */
+  updateAgeOnGet;
+  /**
+   * {@link LRUCache.OptionsBase.updateAgeOnHas}
+   */
+  updateAgeOnHas;
+  /**
+   * {@link LRUCache.OptionsBase.allowStale}
+   */
+  allowStale;
+  /**
+   * {@link LRUCache.OptionsBase.noDisposeOnSet}
+   */
+  noDisposeOnSet;
+  /**
+   * {@link LRUCache.OptionsBase.noUpdateTTL}
+   */
+  noUpdateTTL;
+  /**
+   * {@link LRUCache.OptionsBase.maxEntrySize}
+   */
+  maxEntrySize;
+  /**
+   * {@link LRUCache.OptionsBase.sizeCalculation}
+   */
+  sizeCalculation;
+  /**
+   * {@link LRUCache.OptionsBase.noDeleteOnFetchRejection}
+   */
+  noDeleteOnFetchRejection;
+  /**
+   * {@link LRUCache.OptionsBase.noDeleteOnStaleGet}
+   */
+  noDeleteOnStaleGet;
+  /**
+   * {@link LRUCache.OptionsBase.allowStaleOnFetchAbort}
+   */
+  allowStaleOnFetchAbort;
+  /**
+   * {@link LRUCache.OptionsBase.allowStaleOnFetchRejection}
+   */
+  allowStaleOnFetchRejection;
+  /**
+   * {@link LRUCache.OptionsBase.ignoreFetchAbort}
+   */
+  ignoreFetchAbort;
+  // computed properties
+  #size;
+  #calculatedSize;
+  #keyMap;
+  #keyList;
+  #valList;
+  #next;
+  #prev;
+  #head;
+  #tail;
+  #free;
+  #disposed;
+  #sizes;
+  #starts;
+  #ttls;
+  #hasDispose;
+  #hasFetchMethod;
+  #hasDisposeAfter;
+  /**
+   * Do not call this method unless you need to inspect the
+   * inner workings of the cache.  If anything returned by this
+   * object is modified in any way, strange breakage may occur.
+   *
+   * These fields are private for a reason!
+   *
+   * @internal
+   */
+  static unsafeExposeInternals(c) {
+    return {
+      // properties
+      starts: c.#starts,
+      ttls: c.#ttls,
+      sizes: c.#sizes,
+      keyMap: c.#keyMap,
+      keyList: c.#keyList,
+      valList: c.#valList,
+      next: c.#next,
+      prev: c.#prev,
+      get head() {
+        return c.#head;
+      },
+      get tail() {
+        return c.#tail;
+      },
+      free: c.#free,
+      // methods
+      isBackgroundFetch: (p) => c.#isBackgroundFetch(p),
+      backgroundFetch: (k, index, options, context) => c.#backgroundFetch(k, index, options, context),
+      moveToTail: (index) => c.#moveToTail(index),
+      indexes: (options) => c.#indexes(options),
+      rindexes: (options) => c.#rindexes(options),
+      isStale: (index) => c.#isStale(index)
+    };
+  }
+  // Protected read-only members
+  /**
+   * {@link LRUCache.OptionsBase.max} (read-only)
+   */
+  get max() {
+    return this.#max;
+  }
+  /**
+   * {@link LRUCache.OptionsBase.maxSize} (read-only)
+   */
+  get maxSize() {
+    return this.#maxSize;
+  }
+  /**
+   * The total computed size of items in the cache (read-only)
+   */
+  get calculatedSize() {
+    return this.#calculatedSize;
+  }
+  /**
+   * The number of items stored in the cache (read-only)
+   */
+  get size() {
+    return this.#size;
+  }
+  /**
+   * {@link LRUCache.OptionsBase.fetchMethod} (read-only)
+   */
+  get fetchMethod() {
+    return this.#fetchMethod;
+  }
+  /**
+   * {@link LRUCache.OptionsBase.dispose} (read-only)
+   */
+  get dispose() {
+    return this.#dispose;
+  }
+  /**
+   * {@link LRUCache.OptionsBase.disposeAfter} (read-only)
+   */
+  get disposeAfter() {
+    return this.#disposeAfter;
+  }
+  constructor(options) {
+    const { max = 0, ttl, ttlResolution = 1, ttlAutopurge, updateAgeOnGet, updateAgeOnHas, allowStale, dispose, disposeAfter, noDisposeOnSet, noUpdateTTL, maxSize = 0, maxEntrySize = 0, sizeCalculation, fetchMethod, noDeleteOnFetchRejection, noDeleteOnStaleGet, allowStaleOnFetchRejection, allowStaleOnFetchAbort, ignoreFetchAbort } = options;
+    if (max !== 0 && !isPosInt(max)) {
+      throw new TypeError("max option must be a nonnegative integer");
+    }
+    const UintArray = max ? getUintArray(max) : Array;
+    if (!UintArray) {
+      throw new Error("invalid max value: " + max);
+    }
+    this.#max = max;
+    this.#maxSize = maxSize;
+    this.maxEntrySize = maxEntrySize || this.#maxSize;
+    this.sizeCalculation = sizeCalculation;
+    if (this.sizeCalculation) {
+      if (!this.#maxSize && !this.maxEntrySize) {
+        throw new TypeError("cannot set sizeCalculation without setting maxSize or maxEntrySize");
+      }
+      if (typeof this.sizeCalculation !== "function") {
+        throw new TypeError("sizeCalculation set to non-function");
+      }
+    }
+    if (fetchMethod !== void 0 && typeof fetchMethod !== "function") {
+      throw new TypeError("fetchMethod must be a function if specified");
+    }
+    this.#fetchMethod = fetchMethod;
+    this.#hasFetchMethod = !!fetchMethod;
+    this.#keyMap = /* @__PURE__ */ new Map();
+    this.#keyList = new Array(max).fill(void 0);
+    this.#valList = new Array(max).fill(void 0);
+    this.#next = new UintArray(max);
+    this.#prev = new UintArray(max);
+    this.#head = 0;
+    this.#tail = 0;
+    this.#free = Stack.create(max);
+    this.#size = 0;
+    this.#calculatedSize = 0;
+    if (typeof dispose === "function") {
+      this.#dispose = dispose;
+    }
+    if (typeof disposeAfter === "function") {
+      this.#disposeAfter = disposeAfter;
+      this.#disposed = [];
+    } else {
+      this.#disposeAfter = void 0;
+      this.#disposed = void 0;
+    }
+    this.#hasDispose = !!this.#dispose;
+    this.#hasDisposeAfter = !!this.#disposeAfter;
+    this.noDisposeOnSet = !!noDisposeOnSet;
+    this.noUpdateTTL = !!noUpdateTTL;
+    this.noDeleteOnFetchRejection = !!noDeleteOnFetchRejection;
+    this.allowStaleOnFetchRejection = !!allowStaleOnFetchRejection;
+    this.allowStaleOnFetchAbort = !!allowStaleOnFetchAbort;
+    this.ignoreFetchAbort = !!ignoreFetchAbort;
+    if (this.maxEntrySize !== 0) {
+      if (this.#maxSize !== 0) {
+        if (!isPosInt(this.#maxSize)) {
+          throw new TypeError("maxSize must be a positive integer if specified");
+        }
+      }
+      if (!isPosInt(this.maxEntrySize)) {
+        throw new TypeError("maxEntrySize must be a positive integer if specified");
+      }
+      this.#initializeSizeTracking();
+    }
+    this.allowStale = !!allowStale;
+    this.noDeleteOnStaleGet = !!noDeleteOnStaleGet;
+    this.updateAgeOnGet = !!updateAgeOnGet;
+    this.updateAgeOnHas = !!updateAgeOnHas;
+    this.ttlResolution = isPosInt(ttlResolution) || ttlResolution === 0 ? ttlResolution : 1;
+    this.ttlAutopurge = !!ttlAutopurge;
+    this.ttl = ttl || 0;
+    if (this.ttl) {
+      if (!isPosInt(this.ttl)) {
+        throw new TypeError("ttl must be a positive integer if specified");
+      }
+      this.#initializeTTLTracking();
+    }
+    if (this.#max === 0 && this.ttl === 0 && this.#maxSize === 0) {
+      throw new TypeError("At least one of max, maxSize, or ttl is required");
+    }
+    if (!this.ttlAutopurge && !this.#max && !this.#maxSize) {
+      const code = "LRU_CACHE_UNBOUNDED";
+      if (shouldWarn(code)) {
+        warned.add(code);
+        const msg = "TTL caching without ttlAutopurge, max, or maxSize can result in unbounded memory consumption.";
+        emitWarning(msg, "UnboundedCacheWarning", code, _LRUCache);
+      }
+    }
+  }
+  /**
+   * Return the remaining TTL time for a given entry key
+   */
+  getRemainingTTL(key) {
+    return this.#keyMap.has(key) ? Infinity : 0;
+  }
+  #initializeTTLTracking() {
+    const ttls = new ZeroArray(this.#max);
+    const starts = new ZeroArray(this.#max);
+    this.#ttls = ttls;
+    this.#starts = starts;
+    this.#setItemTTL = (index, ttl, start = perf.now()) => {
+      starts[index] = ttl !== 0 ? start : 0;
+      ttls[index] = ttl;
+      if (ttl !== 0 && this.ttlAutopurge) {
+        const t = setTimeout(() => {
+          if (this.#isStale(index)) {
+            this.delete(this.#keyList[index]);
+          }
+        }, ttl + 1);
+        if (t.unref) {
+          t.unref();
+        }
+      }
+    };
+    this.#updateItemAge = (index) => {
+      starts[index] = ttls[index] !== 0 ? perf.now() : 0;
+    };
+    this.#statusTTL = (status, index) => {
+      if (ttls[index]) {
+        const ttl = ttls[index];
+        const start = starts[index];
+        if (!ttl || !start)
+          return;
+        status.ttl = ttl;
+        status.start = start;
+        status.now = cachedNow || getNow();
+        const age = status.now - start;
+        status.remainingTTL = ttl - age;
+      }
+    };
+    let cachedNow = 0;
+    const getNow = () => {
+      const n = perf.now();
+      if (this.ttlResolution > 0) {
+        cachedNow = n;
+        const t = setTimeout(() => cachedNow = 0, this.ttlResolution);
+        if (t.unref) {
+          t.unref();
+        }
+      }
+      return n;
+    };
+    this.getRemainingTTL = (key) => {
+      const index = this.#keyMap.get(key);
+      if (index === void 0) {
+        return 0;
+      }
+      const ttl = ttls[index];
+      const start = starts[index];
+      if (!ttl || !start) {
+        return Infinity;
+      }
+      const age = (cachedNow || getNow()) - start;
+      return ttl - age;
+    };
+    this.#isStale = (index) => {
+      const s = starts[index];
+      const t = ttls[index];
+      return !!t && !!s && (cachedNow || getNow()) - s > t;
+    };
+  }
+  // conditionally set private methods related to TTL
+  #updateItemAge = () => {
+  };
+  #statusTTL = () => {
+  };
+  #setItemTTL = () => {
+  };
+  /* c8 ignore stop */
+  #isStale = () => false;
+  #initializeSizeTracking() {
+    const sizes = new ZeroArray(this.#max);
+    this.#calculatedSize = 0;
+    this.#sizes = sizes;
+    this.#removeItemSize = (index) => {
+      this.#calculatedSize -= sizes[index];
+      sizes[index] = 0;
+    };
+    this.#requireSize = (k, v, size, sizeCalculation) => {
+      if (this.#isBackgroundFetch(v)) {
+        return 0;
+      }
+      if (!isPosInt(size)) {
+        if (sizeCalculation) {
+          if (typeof sizeCalculation !== "function") {
+            throw new TypeError("sizeCalculation must be a function");
+          }
+          size = sizeCalculation(v, k);
+          if (!isPosInt(size)) {
+            throw new TypeError("sizeCalculation return invalid (expect positive integer)");
+          }
+        } else {
+          throw new TypeError("invalid size value (must be positive integer). When maxSize or maxEntrySize is used, sizeCalculation or size must be set.");
+        }
+      }
+      return size;
+    };
+    this.#addItemSize = (index, size, status) => {
+      sizes[index] = size;
+      if (this.#maxSize) {
+        const maxSize = this.#maxSize - sizes[index];
+        while (this.#calculatedSize > maxSize) {
+          this.#evict(true);
+        }
+      }
+      this.#calculatedSize += sizes[index];
+      if (status) {
+        status.entrySize = size;
+        status.totalCalculatedSize = this.#calculatedSize;
+      }
+    };
+  }
+  #removeItemSize = (_i) => {
+  };
+  #addItemSize = (_i, _s, _st) => {
+  };
+  #requireSize = (_k, _v, size, sizeCalculation) => {
+    if (size || sizeCalculation) {
+      throw new TypeError("cannot set size without setting maxSize or maxEntrySize on cache");
+    }
+    return 0;
+  };
+  *#indexes({ allowStale = this.allowStale } = {}) {
+    if (this.#size) {
+      for (let i = this.#tail; true; ) {
+        if (!this.#isValidIndex(i)) {
+          break;
+        }
+        if (allowStale || !this.#isStale(i)) {
+          yield i;
+        }
+        if (i === this.#head) {
+          break;
+        } else {
+          i = this.#prev[i];
+        }
+      }
+    }
+  }
+  *#rindexes({ allowStale = this.allowStale } = {}) {
+    if (this.#size) {
+      for (let i = this.#head; true; ) {
+        if (!this.#isValidIndex(i)) {
+          break;
+        }
+        if (allowStale || !this.#isStale(i)) {
+          yield i;
+        }
+        if (i === this.#tail) {
+          break;
+        } else {
+          i = this.#next[i];
+        }
+      }
+    }
+  }
+  #isValidIndex(index) {
+    return index !== void 0 && this.#keyMap.get(this.#keyList[index]) === index;
+  }
+  /**
+   * Return a generator yielding `[key, value]` pairs,
+   * in order from most recently used to least recently used.
+   */
+  *entries() {
+    for (const i of this.#indexes()) {
+      if (this.#valList[i] !== void 0 && this.#keyList[i] !== void 0 && !this.#isBackgroundFetch(this.#valList[i])) {
+        yield [this.#keyList[i], this.#valList[i]];
+      }
+    }
+  }
+  /**
+   * Inverse order version of {@link LRUCache.entries}
+   *
+   * Return a generator yielding `[key, value]` pairs,
+   * in order from least recently used to most recently used.
+   */
+  *rentries() {
+    for (const i of this.#rindexes()) {
+      if (this.#valList[i] !== void 0 && this.#keyList[i] !== void 0 && !this.#isBackgroundFetch(this.#valList[i])) {
+        yield [this.#keyList[i], this.#valList[i]];
+      }
+    }
+  }
+  /**
+   * Return a generator yielding the keys in the cache,
+   * in order from most recently used to least recently used.
+   */
+  *keys() {
+    for (const i of this.#indexes()) {
+      const k = this.#keyList[i];
+      if (k !== void 0 && !this.#isBackgroundFetch(this.#valList[i])) {
+        yield k;
+      }
+    }
+  }
+  /**
+   * Inverse order version of {@link LRUCache.keys}
+   *
+   * Return a generator yielding the keys in the cache,
+   * in order from least recently used to most recently used.
+   */
+  *rkeys() {
+    for (const i of this.#rindexes()) {
+      const k = this.#keyList[i];
+      if (k !== void 0 && !this.#isBackgroundFetch(this.#valList[i])) {
+        yield k;
+      }
+    }
+  }
+  /**
+   * Return a generator yielding the values in the cache,
+   * in order from most recently used to least recently used.
+   */
+  *values() {
+    for (const i of this.#indexes()) {
+      const v = this.#valList[i];
+      if (v !== void 0 && !this.#isBackgroundFetch(this.#valList[i])) {
+        yield this.#valList[i];
+      }
+    }
+  }
+  /**
+   * Inverse order version of {@link LRUCache.values}
+   *
+   * Return a generator yielding the values in the cache,
+   * in order from least recently used to most recently used.
+   */
+  *rvalues() {
+    for (const i of this.#rindexes()) {
+      const v = this.#valList[i];
+      if (v !== void 0 && !this.#isBackgroundFetch(this.#valList[i])) {
+        yield this.#valList[i];
+      }
+    }
+  }
+  /**
+   * Iterating over the cache itself yields the same results as
+   * {@link LRUCache.entries}
+   */
+  [Symbol.iterator]() {
+    return this.entries();
+  }
+  /**
+   * A String value that is used in the creation of the default string description of an object.
+   * Called by the built-in method Object.prototype.toString.
+   */
+  [Symbol.toStringTag] = "LRUCache";
+  /**
+   * Find a value for which the supplied fn method returns a truthy value,
+   * similar to Array.find().  fn is called as fn(value, key, cache).
+   */
+  find(fn, getOptions = {}) {
+    for (const i of this.#indexes()) {
+      const v = this.#valList[i];
+      const value = this.#isBackgroundFetch(v) ? v.__staleWhileFetching : v;
+      if (value === void 0)
+        continue;
+      if (fn(value, this.#keyList[i], this)) {
+        return this.get(this.#keyList[i], getOptions);
+      }
+    }
+  }
+  /**
+   * Call the supplied function on each item in the cache, in order from
+   * most recently used to least recently used.  fn is called as
+   * fn(value, key, cache).  Does not update age or recenty of use.
+   * Does not iterate over stale values.
+   */
+  forEach(fn, thisp = this) {
+    for (const i of this.#indexes()) {
+      const v = this.#valList[i];
+      const value = this.#isBackgroundFetch(v) ? v.__staleWhileFetching : v;
+      if (value === void 0)
+        continue;
+      fn.call(thisp, value, this.#keyList[i], this);
+    }
+  }
+  /**
+   * The same as {@link LRUCache.forEach} but items are iterated over in
+   * reverse order.  (ie, less recently used items are iterated over first.)
+   */
+  rforEach(fn, thisp = this) {
+    for (const i of this.#rindexes()) {
+      const v = this.#valList[i];
+      const value = this.#isBackgroundFetch(v) ? v.__staleWhileFetching : v;
+      if (value === void 0)
+        continue;
+      fn.call(thisp, value, this.#keyList[i], this);
+    }
+  }
+  /**
+   * Delete any stale entries. Returns true if anything was removed,
+   * false otherwise.
+   */
+  purgeStale() {
+    let deleted = false;
+    for (const i of this.#rindexes({ allowStale: true })) {
+      if (this.#isStale(i)) {
+        this.delete(this.#keyList[i]);
+        deleted = true;
+      }
+    }
+    return deleted;
+  }
+  /**
+   * Get the extended info about a given entry, to get its value, size, and
+   * TTL info simultaneously. Like {@link LRUCache#dump}, but just for a
+   * single key. Always returns stale values, if their info is found in the
+   * cache, so be sure to check for expired TTLs if relevant.
+   */
+  info(key) {
+    const i = this.#keyMap.get(key);
+    if (i === void 0)
+      return void 0;
+    const v = this.#valList[i];
+    const value = this.#isBackgroundFetch(v) ? v.__staleWhileFetching : v;
+    if (value === void 0)
+      return void 0;
+    const entry = { value };
+    if (this.#ttls && this.#starts) {
+      const ttl = this.#ttls[i];
+      const start = this.#starts[i];
+      if (ttl && start) {
+        const remain = ttl - (perf.now() - start);
+        entry.ttl = remain;
+        entry.start = Date.now();
+      }
+    }
+    if (this.#sizes) {
+      entry.size = this.#sizes[i];
+    }
+    return entry;
+  }
+  /**
+   * Return an array of [key, {@link LRUCache.Entry}] tuples which can be
+   * passed to cache.load()
+   */
+  dump() {
+    const arr = [];
+    for (const i of this.#indexes({ allowStale: true })) {
+      const key = this.#keyList[i];
+      const v = this.#valList[i];
+      const value = this.#isBackgroundFetch(v) ? v.__staleWhileFetching : v;
+      if (value === void 0 || key === void 0)
+        continue;
+      const entry = { value };
+      if (this.#ttls && this.#starts) {
+        entry.ttl = this.#ttls[i];
+        const age = perf.now() - this.#starts[i];
+        entry.start = Math.floor(Date.now() - age);
+      }
+      if (this.#sizes) {
+        entry.size = this.#sizes[i];
+      }
+      arr.unshift([key, entry]);
+    }
+    return arr;
+  }
+  /**
+   * Reset the cache and load in the items in entries in the order listed.
+   * Note that the shape of the resulting cache may be different if the
+   * same options are not used in both caches.
+   */
+  load(arr) {
+    this.clear();
+    for (const [key, entry] of arr) {
+      if (entry.start) {
+        const age = Date.now() - entry.start;
+        entry.start = perf.now() - age;
+      }
+      this.set(key, entry.value, entry);
+    }
+  }
+  /**
+   * Add a value to the cache.
+   *
+   * Note: if `undefined` is specified as a value, this is an alias for
+   * {@link LRUCache#delete}
+   */
+  set(k, v, setOptions = {}) {
+    if (v === void 0) {
+      this.delete(k);
+      return this;
+    }
+    const { ttl = this.ttl, start, noDisposeOnSet = this.noDisposeOnSet, sizeCalculation = this.sizeCalculation, status } = setOptions;
+    let { noUpdateTTL = this.noUpdateTTL } = setOptions;
+    const size = this.#requireSize(k, v, setOptions.size || 0, sizeCalculation);
+    if (this.maxEntrySize && size > this.maxEntrySize) {
+      if (status) {
+        status.set = "miss";
+        status.maxEntrySizeExceeded = true;
+      }
+      this.delete(k);
+      return this;
+    }
+    let index = this.#size === 0 ? void 0 : this.#keyMap.get(k);
+    if (index === void 0) {
+      index = this.#size === 0 ? this.#tail : this.#free.length !== 0 ? this.#free.pop() : this.#size === this.#max ? this.#evict(false) : this.#size;
+      this.#keyList[index] = k;
+      this.#valList[index] = v;
+      this.#keyMap.set(k, index);
+      this.#next[this.#tail] = index;
+      this.#prev[index] = this.#tail;
+      this.#tail = index;
+      this.#size++;
+      this.#addItemSize(index, size, status);
+      if (status)
+        status.set = "add";
+      noUpdateTTL = false;
+    } else {
+      this.#moveToTail(index);
+      const oldVal = this.#valList[index];
+      if (v !== oldVal) {
+        if (this.#hasFetchMethod && this.#isBackgroundFetch(oldVal)) {
+          oldVal.__abortController.abort(new Error("replaced"));
+          const { __staleWhileFetching: s } = oldVal;
+          if (s !== void 0 && !noDisposeOnSet) {
+            if (this.#hasDispose) {
+              this.#dispose?.(s, k, "set");
+            }
+            if (this.#hasDisposeAfter) {
+              this.#disposed?.push([s, k, "set"]);
+            }
+          }
+        } else if (!noDisposeOnSet) {
+          if (this.#hasDispose) {
+            this.#dispose?.(oldVal, k, "set");
+          }
+          if (this.#hasDisposeAfter) {
+            this.#disposed?.push([oldVal, k, "set"]);
+          }
+        }
+        this.#removeItemSize(index);
+        this.#addItemSize(index, size, status);
+        this.#valList[index] = v;
+        if (status) {
+          status.set = "replace";
+          const oldValue = oldVal && this.#isBackgroundFetch(oldVal) ? oldVal.__staleWhileFetching : oldVal;
+          if (oldValue !== void 0)
+            status.oldValue = oldValue;
+        }
+      } else if (status) {
+        status.set = "update";
+      }
+    }
+    if (ttl !== 0 && !this.#ttls) {
+      this.#initializeTTLTracking();
+    }
+    if (this.#ttls) {
+      if (!noUpdateTTL) {
+        this.#setItemTTL(index, ttl, start);
+      }
+      if (status)
+        this.#statusTTL(status, index);
+    }
+    if (!noDisposeOnSet && this.#hasDisposeAfter && this.#disposed) {
+      const dt = this.#disposed;
+      let task;
+      while (task = dt?.shift()) {
+        this.#disposeAfter?.(...task);
+      }
+    }
+    return this;
+  }
+  /**
+   * Evict the least recently used item, returning its value or
+   * `undefined` if cache is empty.
+   */
+  pop() {
+    try {
+      while (this.#size) {
+        const val = this.#valList[this.#head];
+        this.#evict(true);
+        if (this.#isBackgroundFetch(val)) {
+          if (val.__staleWhileFetching) {
+            return val.__staleWhileFetching;
+          }
+        } else if (val !== void 0) {
+          return val;
+        }
+      }
+    } finally {
+      if (this.#hasDisposeAfter && this.#disposed) {
+        const dt = this.#disposed;
+        let task;
+        while (task = dt?.shift()) {
+          this.#disposeAfter?.(...task);
+        }
+      }
+    }
+  }
+  #evict(free) {
+    const head = this.#head;
+    const k = this.#keyList[head];
+    const v = this.#valList[head];
+    if (this.#hasFetchMethod && this.#isBackgroundFetch(v)) {
+      v.__abortController.abort(new Error("evicted"));
+    } else if (this.#hasDispose || this.#hasDisposeAfter) {
+      if (this.#hasDispose) {
+        this.#dispose?.(v, k, "evict");
+      }
+      if (this.#hasDisposeAfter) {
+        this.#disposed?.push([v, k, "evict"]);
+      }
+    }
+    this.#removeItemSize(head);
+    if (free) {
+      this.#keyList[head] = void 0;
+      this.#valList[head] = void 0;
+      this.#free.push(head);
+    }
+    if (this.#size === 1) {
+      this.#head = this.#tail = 0;
+      this.#free.length = 0;
+    } else {
+      this.#head = this.#next[head];
+    }
+    this.#keyMap.delete(k);
+    this.#size--;
+    return head;
+  }
+  /**
+   * Check if a key is in the cache, without updating the recency of use.
+   * Will return false if the item is stale, even though it is technically
+   * in the cache.
+   *
+   * Will not update item age unless
+   * {@link LRUCache.OptionsBase.updateAgeOnHas} is set.
+   */
+  has(k, hasOptions = {}) {
+    const { updateAgeOnHas = this.updateAgeOnHas, status } = hasOptions;
+    const index = this.#keyMap.get(k);
+    if (index !== void 0) {
+      const v = this.#valList[index];
+      if (this.#isBackgroundFetch(v) && v.__staleWhileFetching === void 0) {
+        return false;
+      }
+      if (!this.#isStale(index)) {
+        if (updateAgeOnHas) {
+          this.#updateItemAge(index);
+        }
+        if (status) {
+          status.has = "hit";
+          this.#statusTTL(status, index);
+        }
+        return true;
+      } else if (status) {
+        status.has = "stale";
+        this.#statusTTL(status, index);
+      }
+    } else if (status) {
+      status.has = "miss";
+    }
+    return false;
+  }
+  /**
+   * Like {@link LRUCache#get} but doesn't update recency or delete stale
+   * items.
+   *
+   * Returns `undefined` if the item is stale, unless
+   * {@link LRUCache.OptionsBase.allowStale} is set.
+   */
+  peek(k, peekOptions = {}) {
+    const { allowStale = this.allowStale } = peekOptions;
+    const index = this.#keyMap.get(k);
+    if (index === void 0 || !allowStale && this.#isStale(index)) {
+      return;
+    }
+    const v = this.#valList[index];
+    return this.#isBackgroundFetch(v) ? v.__staleWhileFetching : v;
+  }
+  #backgroundFetch(k, index, options, context) {
+    const v = index === void 0 ? void 0 : this.#valList[index];
+    if (this.#isBackgroundFetch(v)) {
+      return v;
+    }
+    const ac = new AC();
+    const { signal } = options;
+    signal?.addEventListener("abort", () => ac.abort(signal.reason), {
+      signal: ac.signal
+    });
+    const fetchOpts = {
+      signal: ac.signal,
+      options,
+      context
+    };
+    const cb = (v2, updateCache = false) => {
+      const { aborted } = ac.signal;
+      const ignoreAbort = options.ignoreFetchAbort && v2 !== void 0;
+      if (options.status) {
+        if (aborted && !updateCache) {
+          options.status.fetchAborted = true;
+          options.status.fetchError = ac.signal.reason;
+          if (ignoreAbort)
+            options.status.fetchAbortIgnored = true;
+        } else {
+          options.status.fetchResolved = true;
+        }
+      }
+      if (aborted && !ignoreAbort && !updateCache) {
+        return fetchFail(ac.signal.reason);
+      }
+      const bf2 = p;
+      if (this.#valList[index] === p) {
+        if (v2 === void 0) {
+          if (bf2.__staleWhileFetching) {
+            this.#valList[index] = bf2.__staleWhileFetching;
+          } else {
+            this.delete(k);
+          }
+        } else {
+          if (options.status)
+            options.status.fetchUpdated = true;
+          this.set(k, v2, fetchOpts.options);
+        }
+      }
+      return v2;
+    };
+    const eb = (er) => {
+      if (options.status) {
+        options.status.fetchRejected = true;
+        options.status.fetchError = er;
+      }
+      return fetchFail(er);
+    };
+    const fetchFail = (er) => {
+      const { aborted } = ac.signal;
+      const allowStaleAborted = aborted && options.allowStaleOnFetchAbort;
+      const allowStale = allowStaleAborted || options.allowStaleOnFetchRejection;
+      const noDelete = allowStale || options.noDeleteOnFetchRejection;
+      const bf2 = p;
+      if (this.#valList[index] === p) {
+        const del = !noDelete || bf2.__staleWhileFetching === void 0;
+        if (del) {
+          this.delete(k);
+        } else if (!allowStaleAborted) {
+          this.#valList[index] = bf2.__staleWhileFetching;
+        }
+      }
+      if (allowStale) {
+        if (options.status && bf2.__staleWhileFetching !== void 0) {
+          options.status.returnedStale = true;
+        }
+        return bf2.__staleWhileFetching;
+      } else if (bf2.__returned === bf2) {
+        throw er;
+      }
+    };
+    const pcall = (res, rej) => {
+      const fmp = this.#fetchMethod?.(k, v, fetchOpts);
+      if (fmp && fmp instanceof Promise) {
+        fmp.then((v2) => res(v2 === void 0 ? void 0 : v2), rej);
+      }
+      ac.signal.addEventListener("abort", () => {
+        if (!options.ignoreFetchAbort || options.allowStaleOnFetchAbort) {
+          res(void 0);
+          if (options.allowStaleOnFetchAbort) {
+            res = (v2) => cb(v2, true);
+          }
+        }
+      });
+    };
+    if (options.status)
+      options.status.fetchDispatched = true;
+    const p = new Promise(pcall).then(cb, eb);
+    const bf = Object.assign(p, {
+      __abortController: ac,
+      __staleWhileFetching: v,
+      __returned: void 0
+    });
+    if (index === void 0) {
+      this.set(k, bf, { ...fetchOpts.options, status: void 0 });
+      index = this.#keyMap.get(k);
+    } else {
+      this.#valList[index] = bf;
+    }
+    return bf;
+  }
+  #isBackgroundFetch(p) {
+    if (!this.#hasFetchMethod)
+      return false;
+    const b = p;
+    return !!b && b instanceof Promise && b.hasOwnProperty("__staleWhileFetching") && b.__abortController instanceof AC;
+  }
+  async fetch(k, fetchOptions = {}) {
+    const {
+      // get options
+      allowStale = this.allowStale,
+      updateAgeOnGet = this.updateAgeOnGet,
+      noDeleteOnStaleGet = this.noDeleteOnStaleGet,
+      // set options
+      ttl = this.ttl,
+      noDisposeOnSet = this.noDisposeOnSet,
+      size = 0,
+      sizeCalculation = this.sizeCalculation,
+      noUpdateTTL = this.noUpdateTTL,
+      // fetch exclusive options
+      noDeleteOnFetchRejection = this.noDeleteOnFetchRejection,
+      allowStaleOnFetchRejection = this.allowStaleOnFetchRejection,
+      ignoreFetchAbort = this.ignoreFetchAbort,
+      allowStaleOnFetchAbort = this.allowStaleOnFetchAbort,
+      context,
+      forceRefresh = false,
+      status,
+      signal
+    } = fetchOptions;
+    if (!this.#hasFetchMethod) {
+      if (status)
+        status.fetch = "get";
+      return this.get(k, {
+        allowStale,
+        updateAgeOnGet,
+        noDeleteOnStaleGet,
+        status
+      });
+    }
+    const options = {
+      allowStale,
+      updateAgeOnGet,
+      noDeleteOnStaleGet,
+      ttl,
+      noDisposeOnSet,
+      size,
+      sizeCalculation,
+      noUpdateTTL,
+      noDeleteOnFetchRejection,
+      allowStaleOnFetchRejection,
+      allowStaleOnFetchAbort,
+      ignoreFetchAbort,
+      status,
+      signal
+    };
+    let index = this.#keyMap.get(k);
+    if (index === void 0) {
+      if (status)
+        status.fetch = "miss";
+      const p = this.#backgroundFetch(k, index, options, context);
+      return p.__returned = p;
+    } else {
+      const v = this.#valList[index];
+      if (this.#isBackgroundFetch(v)) {
+        const stale = allowStale && v.__staleWhileFetching !== void 0;
+        if (status) {
+          status.fetch = "inflight";
+          if (stale)
+            status.returnedStale = true;
+        }
+        return stale ? v.__staleWhileFetching : v.__returned = v;
+      }
+      const isStale = this.#isStale(index);
+      if (!forceRefresh && !isStale) {
+        if (status)
+          status.fetch = "hit";
+        this.#moveToTail(index);
+        if (updateAgeOnGet) {
+          this.#updateItemAge(index);
+        }
+        if (status)
+          this.#statusTTL(status, index);
+        return v;
+      }
+      const p = this.#backgroundFetch(k, index, options, context);
+      const hasStale = p.__staleWhileFetching !== void 0;
+      const staleVal = hasStale && allowStale;
+      if (status) {
+        status.fetch = isStale ? "stale" : "refresh";
+        if (staleVal && isStale)
+          status.returnedStale = true;
+      }
+      return staleVal ? p.__staleWhileFetching : p.__returned = p;
+    }
+  }
+  /**
+   * Return a value from the cache. Will update the recency of the cache
+   * entry found.
+   *
+   * If the key is not found, get() will return `undefined`.
+   */
+  get(k, getOptions = {}) {
+    const { allowStale = this.allowStale, updateAgeOnGet = this.updateAgeOnGet, noDeleteOnStaleGet = this.noDeleteOnStaleGet, status } = getOptions;
+    const index = this.#keyMap.get(k);
+    if (index !== void 0) {
+      const value = this.#valList[index];
+      const fetching = this.#isBackgroundFetch(value);
+      if (status)
+        this.#statusTTL(status, index);
+      if (this.#isStale(index)) {
+        if (status)
+          status.get = "stale";
+        if (!fetching) {
+          if (!noDeleteOnStaleGet) {
+            this.delete(k);
+          }
+          if (status && allowStale)
+            status.returnedStale = true;
+          return allowStale ? value : void 0;
+        } else {
+          if (status && allowStale && value.__staleWhileFetching !== void 0) {
+            status.returnedStale = true;
+          }
+          return allowStale ? value.__staleWhileFetching : void 0;
+        }
+      } else {
+        if (status)
+          status.get = "hit";
+        if (fetching) {
+          return value.__staleWhileFetching;
+        }
+        this.#moveToTail(index);
+        if (updateAgeOnGet) {
+          this.#updateItemAge(index);
+        }
+        return value;
+      }
+    } else if (status) {
+      status.get = "miss";
+    }
+  }
+  #connect(p, n) {
+    this.#prev[n] = p;
+    this.#next[p] = n;
+  }
+  #moveToTail(index) {
+    if (index !== this.#tail) {
+      if (index === this.#head) {
+        this.#head = this.#next[index];
+      } else {
+        this.#connect(this.#prev[index], this.#next[index]);
+      }
+      this.#connect(this.#tail, index);
+      this.#tail = index;
+    }
+  }
+  /**
+   * Deletes a key out of the cache.
+   * Returns true if the key was deleted, false otherwise.
+   */
+  delete(k) {
+    let deleted = false;
+    if (this.#size !== 0) {
+      const index = this.#keyMap.get(k);
+      if (index !== void 0) {
+        deleted = true;
+        if (this.#size === 1) {
+          this.clear();
+        } else {
+          this.#removeItemSize(index);
+          const v = this.#valList[index];
+          if (this.#isBackgroundFetch(v)) {
+            v.__abortController.abort(new Error("deleted"));
+          } else if (this.#hasDispose || this.#hasDisposeAfter) {
+            if (this.#hasDispose) {
+              this.#dispose?.(v, k, "delete");
+            }
+            if (this.#hasDisposeAfter) {
+              this.#disposed?.push([v, k, "delete"]);
+            }
+          }
+          this.#keyMap.delete(k);
+          this.#keyList[index] = void 0;
+          this.#valList[index] = void 0;
+          if (index === this.#tail) {
+            this.#tail = this.#prev[index];
+          } else if (index === this.#head) {
+            this.#head = this.#next[index];
+          } else {
+            const pi = this.#prev[index];
+            this.#next[pi] = this.#next[index];
+            const ni = this.#next[index];
+            this.#prev[ni] = this.#prev[index];
+          }
+          this.#size--;
+          this.#free.push(index);
+        }
+      }
+    }
+    if (this.#hasDisposeAfter && this.#disposed?.length) {
+      const dt = this.#disposed;
+      let task;
+      while (task = dt?.shift()) {
+        this.#disposeAfter?.(...task);
+      }
+    }
+    return deleted;
+  }
+  /**
+   * Clear the cache entirely, throwing away all values.
+   */
+  clear() {
+    for (const index of this.#rindexes({ allowStale: true })) {
+      const v = this.#valList[index];
+      if (this.#isBackgroundFetch(v)) {
+        v.__abortController.abort(new Error("deleted"));
+      } else {
+        const k = this.#keyList[index];
+        if (this.#hasDispose) {
+          this.#dispose?.(v, k, "delete");
+        }
+        if (this.#hasDisposeAfter) {
+          this.#disposed?.push([v, k, "delete"]);
+        }
+      }
+    }
+    this.#keyMap.clear();
+    this.#valList.fill(void 0);
+    this.#keyList.fill(void 0);
+    if (this.#ttls && this.#starts) {
+      this.#ttls.fill(0);
+      this.#starts.fill(0);
+    }
+    if (this.#sizes) {
+      this.#sizes.fill(0);
+    }
+    this.#head = 0;
+    this.#tail = 0;
+    this.#free.length = 0;
+    this.#calculatedSize = 0;
+    this.#size = 0;
+    if (this.#hasDisposeAfter && this.#disposed) {
+      const dt = this.#disposed;
+      let task;
+      while (task = dt?.shift()) {
+        this.#disposeAfter?.(...task);
+      }
+    }
+  }
+};
+
+// node_modules/path-scurry/dist/esm/index.js
+import { posix, win32 } from "path";
+import { fileURLToPath } from "url";
+import * as actualFS from "fs";
+import { lstatSync, readdir as readdirCB, readdirSync, readlinkSync, realpathSync as rps } from "fs";
+import { lstat, readdir, readlink, realpath } from "fs/promises";
+
+// node_modules/minipass/dist/esm/index.js
+import { EventEmitter } from "events";
+import Stream from "stream";
+import { StringDecoder } from "string_decoder";
+var proc = typeof process === "object" && process ? process : {
+  stdout: null,
+  stderr: null
+};
+var isStream = (s) => !!s && typeof s === "object" && (s instanceof Minipass || s instanceof Stream || isReadable(s) || isWritable(s));
+var isReadable = (s) => !!s && typeof s === "object" && s instanceof EventEmitter && typeof s.pipe === "function" && // node core Writable streams have a pipe() method, but it throws
+s.pipe !== Stream.Writable.prototype.pipe;
+var isWritable = (s) => !!s && typeof s === "object" && s instanceof EventEmitter && typeof s.write === "function" && typeof s.end === "function";
+var EOF = Symbol("EOF");
+var MAYBE_EMIT_END = Symbol("maybeEmitEnd");
+var EMITTED_END = Symbol("emittedEnd");
+var EMITTING_END = Symbol("emittingEnd");
+var EMITTED_ERROR = Symbol("emittedError");
+var CLOSED = Symbol("closed");
+var READ = Symbol("read");
+var FLUSH = Symbol("flush");
+var FLUSHCHUNK = Symbol("flushChunk");
+var ENCODING = Symbol("encoding");
+var DECODER = Symbol("decoder");
+var FLOWING = Symbol("flowing");
+var PAUSED = Symbol("paused");
+var RESUME = Symbol("resume");
+var BUFFER = Symbol("buffer");
+var PIPES = Symbol("pipes");
+var BUFFERLENGTH = Symbol("bufferLength");
+var BUFFERPUSH = Symbol("bufferPush");
+var BUFFERSHIFT = Symbol("bufferShift");
+var OBJECTMODE = Symbol("objectMode");
+var DESTROYED = Symbol("destroyed");
+var ERROR = Symbol("error");
+var EMITDATA = Symbol("emitData");
+var EMITEND = Symbol("emitEnd");
+var EMITEND2 = Symbol("emitEnd2");
+var ASYNC = Symbol("async");
+var ABORT = Symbol("abort");
+var ABORTED = Symbol("aborted");
+var SIGNAL = Symbol("signal");
+var DATALISTENERS = Symbol("dataListeners");
+var DISCARDED = Symbol("discarded");
+var defer = (fn) => Promise.resolve().then(fn);
+var nodefer = (fn) => fn();
+var isEndish = (ev) => ev === "end" || ev === "finish" || ev === "prefinish";
+var isArrayBufferLike = (b) => b instanceof ArrayBuffer || !!b && typeof b === "object" && b.constructor && b.constructor.name === "ArrayBuffer" && b.byteLength >= 0;
+var isArrayBufferView = (b) => !Buffer.isBuffer(b) && ArrayBuffer.isView(b);
+var Pipe = class {
+  src;
+  dest;
+  opts;
+  ondrain;
+  constructor(src, dest, opts) {
+    this.src = src;
+    this.dest = dest;
+    this.opts = opts;
+    this.ondrain = () => src[RESUME]();
+    this.dest.on("drain", this.ondrain);
+  }
+  unpipe() {
+    this.dest.removeListener("drain", this.ondrain);
+  }
+  // only here for the prototype
+  /* c8 ignore start */
+  proxyErrors(_er) {
+  }
+  /* c8 ignore stop */
+  end() {
+    this.unpipe();
+    if (this.opts.end)
+      this.dest.end();
+  }
+};
+var PipeProxyErrors = class extends Pipe {
+  unpipe() {
+    this.src.removeListener("error", this.proxyErrors);
+    super.unpipe();
+  }
+  constructor(src, dest, opts) {
+    super(src, dest, opts);
+    this.proxyErrors = (er) => dest.emit("error", er);
+    src.on("error", this.proxyErrors);
+  }
+};
+var isObjectModeOptions = (o) => !!o.objectMode;
+var isEncodingOptions = (o) => !o.objectMode && !!o.encoding && o.encoding !== "buffer";
+var Minipass = class extends EventEmitter {
+  [FLOWING] = false;
+  [PAUSED] = false;
+  [PIPES] = [];
+  [BUFFER] = [];
+  [OBJECTMODE];
+  [ENCODING];
+  [ASYNC];
+  [DECODER];
+  [EOF] = false;
+  [EMITTED_END] = false;
+  [EMITTING_END] = false;
+  [CLOSED] = false;
+  [EMITTED_ERROR] = null;
+  [BUFFERLENGTH] = 0;
+  [DESTROYED] = false;
+  [SIGNAL];
+  [ABORTED] = false;
+  [DATALISTENERS] = 0;
+  [DISCARDED] = false;
+  /**
+   * true if the stream can be written
+   */
+  writable = true;
+  /**
+   * true if the stream can be read
+   */
+  readable = true;
+  /**
+   * If `RType` is Buffer, then options do not need to be provided.
+   * Otherwise, an options object must be provided to specify either
+   * {@link Minipass.SharedOptions.objectMode} or
+   * {@link Minipass.SharedOptions.encoding}, as appropriate.
+   */
+  constructor(...args) {
+    const options = args[0] || {};
+    super();
+    if (options.objectMode && typeof options.encoding === "string") {
+      throw new TypeError("Encoding and objectMode may not be used together");
+    }
+    if (isObjectModeOptions(options)) {
+      this[OBJECTMODE] = true;
+      this[ENCODING] = null;
+    } else if (isEncodingOptions(options)) {
+      this[ENCODING] = options.encoding;
+      this[OBJECTMODE] = false;
+    } else {
+      this[OBJECTMODE] = false;
+      this[ENCODING] = null;
+    }
+    this[ASYNC] = !!options.async;
+    this[DECODER] = this[ENCODING] ? new StringDecoder(this[ENCODING]) : null;
+    if (options && options.debugExposeBuffer === true) {
+      Object.defineProperty(this, "buffer", { get: () => this[BUFFER] });
+    }
+    if (options && options.debugExposePipes === true) {
+      Object.defineProperty(this, "pipes", { get: () => this[PIPES] });
+    }
+    const { signal } = options;
+    if (signal) {
+      this[SIGNAL] = signal;
+      if (signal.aborted) {
+        this[ABORT]();
+      } else {
+        signal.addEventListener("abort", () => this[ABORT]());
+      }
+    }
+  }
+  /**
+   * The amount of data stored in the buffer waiting to be read.
+   *
+   * For Buffer strings, this will be the total byte length.
+   * For string encoding streams, this will be the string character length,
+   * according to JavaScript's `string.length` logic.
+   * For objectMode streams, this is a count of the items waiting to be
+   * emitted.
+   */
+  get bufferLength() {
+    return this[BUFFERLENGTH];
+  }
+  /**
+   * The `BufferEncoding` currently in use, or `null`
+   */
+  get encoding() {
+    return this[ENCODING];
+  }
+  /**
+   * @deprecated - This is a read only property
+   */
+  set encoding(_enc) {
+    throw new Error("Encoding must be set at instantiation time");
+  }
+  /**
+   * @deprecated - Encoding may only be set at instantiation time
+   */
+  setEncoding(_enc) {
+    throw new Error("Encoding must be set at instantiation time");
+  }
+  /**
+   * True if this is an objectMode stream
+   */
+  get objectMode() {
+    return this[OBJECTMODE];
+  }
+  /**
+   * @deprecated - This is a read-only property
+   */
+  set objectMode(_om) {
+    throw new Error("objectMode must be set at instantiation time");
+  }
+  /**
+   * true if this is an async stream
+   */
+  get ["async"]() {
+    return this[ASYNC];
+  }
+  /**
+   * Set to true to make this stream async.
+   *
+   * Once set, it cannot be unset, as this would potentially cause incorrect
+   * behavior.  Ie, a sync stream can be made async, but an async stream
+   * cannot be safely made sync.
+   */
+  set ["async"](a) {
+    this[ASYNC] = this[ASYNC] || !!a;
+  }
+  // drop everything and get out of the flow completely
+  [ABORT]() {
+    this[ABORTED] = true;
+    this.emit("abort", this[SIGNAL]?.reason);
+    this.destroy(this[SIGNAL]?.reason);
+  }
+  /**
+   * True if the stream has been aborted.
+   */
+  get aborted() {
+    return this[ABORTED];
+  }
+  /**
+   * No-op setter. Stream aborted status is set via the AbortSignal provided
+   * in the constructor options.
+   */
+  set aborted(_) {
+  }
+  write(chunk, encoding, cb) {
+    if (this[ABORTED])
+      return false;
+    if (this[EOF])
+      throw new Error("write after end");
+    if (this[DESTROYED]) {
+      this.emit("error", Object.assign(new Error("Cannot call write after a stream was destroyed"), { code: "ERR_STREAM_DESTROYED" }));
+      return true;
+    }
+    if (typeof encoding === "function") {
+      cb = encoding;
+      encoding = "utf8";
+    }
+    if (!encoding)
+      encoding = "utf8";
+    const fn = this[ASYNC] ? defer : nodefer;
+    if (!this[OBJECTMODE] && !Buffer.isBuffer(chunk)) {
+      if (isArrayBufferView(chunk)) {
+        chunk = Buffer.from(chunk.buffer, chunk.byteOffset, chunk.byteLength);
+      } else if (isArrayBufferLike(chunk)) {
+        chunk = Buffer.from(chunk);
+      } else if (typeof chunk !== "string") {
+        throw new Error("Non-contiguous data written to non-objectMode stream");
+      }
+    }
+    if (this[OBJECTMODE]) {
+      if (this[FLOWING] && this[BUFFERLENGTH] !== 0)
+        this[FLUSH](true);
+      if (this[FLOWING])
+        this.emit("data", chunk);
+      else
+        this[BUFFERPUSH](chunk);
+      if (this[BUFFERLENGTH] !== 0)
+        this.emit("readable");
+      if (cb)
+        fn(cb);
+      return this[FLOWING];
+    }
+    if (!chunk.length) {
+      if (this[BUFFERLENGTH] !== 0)
+        this.emit("readable");
+      if (cb)
+        fn(cb);
+      return this[FLOWING];
+    }
+    if (typeof chunk === "string" && // unless it is a string already ready for us to use
+    !(encoding === this[ENCODING] && !this[DECODER]?.lastNeed)) {
+      chunk = Buffer.from(chunk, encoding);
+    }
+    if (Buffer.isBuffer(chunk) && this[ENCODING]) {
+      chunk = this[DECODER].write(chunk);
+    }
+    if (this[FLOWING] && this[BUFFERLENGTH] !== 0)
+      this[FLUSH](true);
+    if (this[FLOWING])
+      this.emit("data", chunk);
+    else
+      this[BUFFERPUSH](chunk);
+    if (this[BUFFERLENGTH] !== 0)
+      this.emit("readable");
+    if (cb)
+      fn(cb);
+    return this[FLOWING];
+  }
+  /**
+   * Low-level explicit read method.
+   *
+   * In objectMode, the argument is ignored, and one item is returned if
+   * available.
+   *
+   * `n` is the number of bytes (or in the case of encoding streams,
+   * characters) to consume. If `n` is not provided, then the entire buffer
+   * is returned, or `null` is returned if no data is available.
+   *
+   * If `n` is greater that the amount of data in the internal buffer,
+   * then `null` is returned.
+   */
+  read(n) {
+    if (this[DESTROYED])
+      return null;
+    this[DISCARDED] = false;
+    if (this[BUFFERLENGTH] === 0 || n === 0 || n && n > this[BUFFERLENGTH]) {
+      this[MAYBE_EMIT_END]();
+      return null;
+    }
+    if (this[OBJECTMODE])
+      n = null;
+    if (this[BUFFER].length > 1 && !this[OBJECTMODE]) {
+      this[BUFFER] = [
+        this[ENCODING] ? this[BUFFER].join("") : Buffer.concat(this[BUFFER], this[BUFFERLENGTH])
+      ];
+    }
+    const ret = this[READ](n || null, this[BUFFER][0]);
+    this[MAYBE_EMIT_END]();
+    return ret;
+  }
+  [READ](n, chunk) {
+    if (this[OBJECTMODE])
+      this[BUFFERSHIFT]();
+    else {
+      const c = chunk;
+      if (n === c.length || n === null)
+        this[BUFFERSHIFT]();
+      else if (typeof c === "string") {
+        this[BUFFER][0] = c.slice(n);
+        chunk = c.slice(0, n);
+        this[BUFFERLENGTH] -= n;
+      } else {
+        this[BUFFER][0] = c.subarray(n);
+        chunk = c.subarray(0, n);
+        this[BUFFERLENGTH] -= n;
+      }
+    }
+    this.emit("data", chunk);
+    if (!this[BUFFER].length && !this[EOF])
+      this.emit("drain");
+    return chunk;
+  }
+  end(chunk, encoding, cb) {
+    if (typeof chunk === "function") {
+      cb = chunk;
+      chunk = void 0;
+    }
+    if (typeof encoding === "function") {
+      cb = encoding;
+      encoding = "utf8";
+    }
+    if (chunk !== void 0)
+      this.write(chunk, encoding);
+    if (cb)
+      this.once("end", cb);
+    this[EOF] = true;
+    this.writable = false;
+    if (this[FLOWING] || !this[PAUSED])
+      this[MAYBE_EMIT_END]();
+    return this;
+  }
+  // don't let the internal resume be overwritten
+  [RESUME]() {
+    if (this[DESTROYED])
+      return;
+    if (!this[DATALISTENERS] && !this[PIPES].length) {
+      this[DISCARDED] = true;
+    }
+    this[PAUSED] = false;
+    this[FLOWING] = true;
+    this.emit("resume");
+    if (this[BUFFER].length)
+      this[FLUSH]();
+    else if (this[EOF])
+      this[MAYBE_EMIT_END]();
+    else
+      this.emit("drain");
+  }
+  /**
+   * Resume the stream if it is currently in a paused state
+   *
+   * If called when there are no pipe destinations or `data` event listeners,
+   * this will place the stream in a "discarded" state, where all data will
+   * be thrown away. The discarded state is removed if a pipe destination or
+   * data handler is added, if pause() is called, or if any synchronous or
+   * asynchronous iteration is started.
+   */
+  resume() {
+    return this[RESUME]();
+  }
+  /**
+   * Pause the stream
+   */
+  pause() {
+    this[FLOWING] = false;
+    this[PAUSED] = true;
+    this[DISCARDED] = false;
+  }
+  /**
+   * true if the stream has been forcibly destroyed
+   */
+  get destroyed() {
+    return this[DESTROYED];
+  }
+  /**
+   * true if the stream is currently in a flowing state, meaning that
+   * any writes will be immediately emitted.
+   */
+  get flowing() {
+    return this[FLOWING];
+  }
+  /**
+   * true if the stream is currently in a paused state
+   */
+  get paused() {
+    return this[PAUSED];
+  }
+  [BUFFERPUSH](chunk) {
+    if (this[OBJECTMODE])
+      this[BUFFERLENGTH] += 1;
+    else
+      this[BUFFERLENGTH] += chunk.length;
+    this[BUFFER].push(chunk);
+  }
+  [BUFFERSHIFT]() {
+    if (this[OBJECTMODE])
+      this[BUFFERLENGTH] -= 1;
+    else
+      this[BUFFERLENGTH] -= this[BUFFER][0].length;
+    return this[BUFFER].shift();
+  }
+  [FLUSH](noDrain = false) {
+    do {
+    } while (this[FLUSHCHUNK](this[BUFFERSHIFT]()) && this[BUFFER].length);
+    if (!noDrain && !this[BUFFER].length && !this[EOF])
+      this.emit("drain");
+  }
+  [FLUSHCHUNK](chunk) {
+    this.emit("data", chunk);
+    return this[FLOWING];
+  }
+  /**
+   * Pipe all data emitted by this stream into the destination provided.
+   *
+   * Triggers the flow of data.
+   */
+  pipe(dest, opts) {
+    if (this[DESTROYED])
+      return dest;
+    this[DISCARDED] = false;
+    const ended = this[EMITTED_END];
+    opts = opts || {};
+    if (dest === proc.stdout || dest === proc.stderr)
+      opts.end = false;
+    else
+      opts.end = opts.end !== false;
+    opts.proxyErrors = !!opts.proxyErrors;
+    if (ended) {
+      if (opts.end)
+        dest.end();
+    } else {
+      this[PIPES].push(!opts.proxyErrors ? new Pipe(this, dest, opts) : new PipeProxyErrors(this, dest, opts));
+      if (this[ASYNC])
+        defer(() => this[RESUME]());
+      else
+        this[RESUME]();
+    }
+    return dest;
+  }
+  /**
+   * Fully unhook a piped destination stream.
+   *
+   * If the destination stream was the only consumer of this stream (ie,
+   * there are no other piped destinations or `'data'` event listeners)
+   * then the flow of data will stop until there is another consumer or
+   * {@link Minipass#resume} is explicitly called.
+   */
+  unpipe(dest) {
+    const p = this[PIPES].find((p2) => p2.dest === dest);
+    if (p) {
+      if (this[PIPES].length === 1) {
+        if (this[FLOWING] && this[DATALISTENERS] === 0) {
+          this[FLOWING] = false;
+        }
+        this[PIPES] = [];
+      } else
+        this[PIPES].splice(this[PIPES].indexOf(p), 1);
+      p.unpipe();
+    }
+  }
+  /**
+   * Alias for {@link Minipass#on}
+   */
+  addListener(ev, handler) {
+    return this.on(ev, handler);
+  }
+  /**
+   * Mostly identical to `EventEmitter.on`, with the following
+   * behavior differences to prevent data loss and unnecessary hangs:
+   *
+   * - Adding a 'data' event handler will trigger the flow of data
+   *
+   * - Adding a 'readable' event handler when there is data waiting to be read
+   *   will cause 'readable' to be emitted immediately.
+   *
+   * - Adding an 'endish' event handler ('end', 'finish', etc.) which has
+   *   already passed will cause the event to be emitted immediately and all
+   *   handlers removed.
+   *
+   * - Adding an 'error' event handler after an error has been emitted will
+   *   cause the event to be re-emitted immediately with the error previously
+   *   raised.
+   */
+  on(ev, handler) {
+    const ret = super.on(ev, handler);
+    if (ev === "data") {
+      this[DISCARDED] = false;
+      this[DATALISTENERS]++;
+      if (!this[PIPES].length && !this[FLOWING]) {
+        this[RESUME]();
+      }
+    } else if (ev === "readable" && this[BUFFERLENGTH] !== 0) {
+      super.emit("readable");
+    } else if (isEndish(ev) && this[EMITTED_END]) {
+      super.emit(ev);
+      this.removeAllListeners(ev);
+    } else if (ev === "error" && this[EMITTED_ERROR]) {
+      const h = handler;
+      if (this[ASYNC])
+        defer(() => h.call(this, this[EMITTED_ERROR]));
+      else
+        h.call(this, this[EMITTED_ERROR]);
+    }
+    return ret;
+  }
+  /**
+   * Alias for {@link Minipass#off}
+   */
+  removeListener(ev, handler) {
+    return this.off(ev, handler);
+  }
+  /**
+   * Mostly identical to `EventEmitter.off`
+   *
+   * If a 'data' event handler is removed, and it was the last consumer
+   * (ie, there are no pipe destinations or other 'data' event listeners),
+   * then the flow of data will stop until there is another consumer or
+   * {@link Minipass#resume} is explicitly called.
+   */
+  off(ev, handler) {
+    const ret = super.off(ev, handler);
+    if (ev === "data") {
+      this[DATALISTENERS] = this.listeners("data").length;
+      if (this[DATALISTENERS] === 0 && !this[DISCARDED] && !this[PIPES].length) {
+        this[FLOWING] = false;
+      }
+    }
+    return ret;
+  }
+  /**
+   * Mostly identical to `EventEmitter.removeAllListeners`
+   *
+   * If all 'data' event handlers are removed, and they were the last consumer
+   * (ie, there are no pipe destinations), then the flow of data will stop
+   * until there is another consumer or {@link Minipass#resume} is explicitly
+   * called.
+   */
+  removeAllListeners(ev) {
+    const ret = super.removeAllListeners(ev);
+    if (ev === "data" || ev === void 0) {
+      this[DATALISTENERS] = 0;
+      if (!this[DISCARDED] && !this[PIPES].length) {
+        this[FLOWING] = false;
+      }
+    }
+    return ret;
+  }
+  /**
+   * true if the 'end' event has been emitted
+   */
+  get emittedEnd() {
+    return this[EMITTED_END];
+  }
+  [MAYBE_EMIT_END]() {
+    if (!this[EMITTING_END] && !this[EMITTED_END] && !this[DESTROYED] && this[BUFFER].length === 0 && this[EOF]) {
+      this[EMITTING_END] = true;
+      this.emit("end");
+      this.emit("prefinish");
+      this.emit("finish");
+      if (this[CLOSED])
+        this.emit("close");
+      this[EMITTING_END] = false;
+    }
+  }
+  /**
+   * Mostly identical to `EventEmitter.emit`, with the following
+   * behavior differences to prevent data loss and unnecessary hangs:
+   *
+   * If the stream has been destroyed, and the event is something other
+   * than 'close' or 'error', then `false` is returned and no handlers
+   * are called.
+   *
+   * If the event is 'end', and has already been emitted, then the event
+   * is ignored. If the stream is in a paused or non-flowing state, then
+   * the event will be deferred until data flow resumes. If the stream is
+   * async, then handlers will be called on the next tick rather than
+   * immediately.
+   *
+   * If the event is 'close', and 'end' has not yet been emitted, then
+   * the event will be deferred until after 'end' is emitted.
+   *
+   * If the event is 'error', and an AbortSignal was provided for the stream,
+   * and there are no listeners, then the event is ignored, matching the
+   * behavior of node core streams in the presense of an AbortSignal.
+   *
+   * If the event is 'finish' or 'prefinish', then all listeners will be
+   * removed after emitting the event, to prevent double-firing.
+   */
+  emit(ev, ...args) {
+    const data = args[0];
+    if (ev !== "error" && ev !== "close" && ev !== DESTROYED && this[DESTROYED]) {
+      return false;
+    } else if (ev === "data") {
+      return !this[OBJECTMODE] && !data ? false : this[ASYNC] ? (defer(() => this[EMITDATA](data)), true) : this[EMITDATA](data);
+    } else if (ev === "end") {
+      return this[EMITEND]();
+    } else if (ev === "close") {
+      this[CLOSED] = true;
+      if (!this[EMITTED_END] && !this[DESTROYED])
+        return false;
+      const ret2 = super.emit("close");
+      this.removeAllListeners("close");
+      return ret2;
+    } else if (ev === "error") {
+      this[EMITTED_ERROR] = data;
+      super.emit(ERROR, data);
+      const ret2 = !this[SIGNAL] || this.listeners("error").length ? super.emit("error", data) : false;
+      this[MAYBE_EMIT_END]();
+      return ret2;
+    } else if (ev === "resume") {
+      const ret2 = super.emit("resume");
+      this[MAYBE_EMIT_END]();
+      return ret2;
+    } else if (ev === "finish" || ev === "prefinish") {
+      const ret2 = super.emit(ev);
+      this.removeAllListeners(ev);
+      return ret2;
+    }
+    const ret = super.emit(ev, ...args);
+    this[MAYBE_EMIT_END]();
+    return ret;
+  }
+  [EMITDATA](data) {
+    for (const p of this[PIPES]) {
+      if (p.dest.write(data) === false)
+        this.pause();
+    }
+    const ret = this[DISCARDED] ? false : super.emit("data", data);
+    this[MAYBE_EMIT_END]();
+    return ret;
+  }
+  [EMITEND]() {
+    if (this[EMITTED_END])
+      return false;
+    this[EMITTED_END] = true;
+    this.readable = false;
+    return this[ASYNC] ? (defer(() => this[EMITEND2]()), true) : this[EMITEND2]();
+  }
+  [EMITEND2]() {
+    if (this[DECODER]) {
+      const data = this[DECODER].end();
+      if (data) {
+        for (const p of this[PIPES]) {
+          p.dest.write(data);
+        }
+        if (!this[DISCARDED])
+          super.emit("data", data);
+      }
+    }
+    for (const p of this[PIPES]) {
+      p.end();
+    }
+    const ret = super.emit("end");
+    this.removeAllListeners("end");
+    return ret;
+  }
+  /**
+   * Return a Promise that resolves to an array of all emitted data once
+   * the stream ends.
+   */
+  async collect() {
+    const buf = Object.assign([], {
+      dataLength: 0
+    });
+    if (!this[OBJECTMODE])
+      buf.dataLength = 0;
+    const p = this.promise();
+    this.on("data", (c) => {
+      buf.push(c);
+      if (!this[OBJECTMODE])
+        buf.dataLength += c.length;
+    });
+    await p;
+    return buf;
+  }
+  /**
+   * Return a Promise that resolves to the concatenation of all emitted data
+   * once the stream ends.
+   *
+   * Not allowed on objectMode streams.
+   */
+  async concat() {
+    if (this[OBJECTMODE]) {
+      throw new Error("cannot concat in objectMode");
+    }
+    const buf = await this.collect();
+    return this[ENCODING] ? buf.join("") : Buffer.concat(buf, buf.dataLength);
+  }
+  /**
+   * Return a void Promise that resolves once the stream ends.
+   */
+  async promise() {
+    return new Promise((resolve, reject) => {
+      this.on(DESTROYED, () => reject(new Error("stream destroyed")));
+      this.on("error", (er) => reject(er));
+      this.on("end", () => resolve());
+    });
+  }
+  /**
+   * Asynchronous `for await of` iteration.
+   *
+   * This will continue emitting all chunks until the stream terminates.
+   */
+  [Symbol.asyncIterator]() {
+    this[DISCARDED] = false;
+    let stopped = false;
+    const stop = async () => {
+      this.pause();
+      stopped = true;
+      return { value: void 0, done: true };
+    };
+    const next = () => {
+      if (stopped)
+        return stop();
+      const res = this.read();
+      if (res !== null)
+        return Promise.resolve({ done: false, value: res });
+      if (this[EOF])
+        return stop();
+      let resolve;
+      let reject;
+      const onerr = (er) => {
+        this.off("data", ondata);
+        this.off("end", onend);
+        this.off(DESTROYED, ondestroy);
+        stop();
+        reject(er);
+      };
+      const ondata = (value) => {
+        this.off("error", onerr);
+        this.off("end", onend);
+        this.off(DESTROYED, ondestroy);
+        this.pause();
+        resolve({ value, done: !!this[EOF] });
+      };
+      const onend = () => {
+        this.off("error", onerr);
+        this.off("data", ondata);
+        this.off(DESTROYED, ondestroy);
+        stop();
+        resolve({ done: true, value: void 0 });
+      };
+      const ondestroy = () => onerr(new Error("stream destroyed"));
+      return new Promise((res2, rej) => {
+        reject = rej;
+        resolve = res2;
+        this.once(DESTROYED, ondestroy);
+        this.once("error", onerr);
+        this.once("end", onend);
+        this.once("data", ondata);
+      });
+    };
+    return {
+      next,
+      throw: stop,
+      return: stop,
+      [Symbol.asyncIterator]() {
+        return this;
+      }
+    };
+  }
+  /**
+   * Synchronous `for of` iteration.
+   *
+   * The iteration will terminate when the internal buffer runs out, even
+   * if the stream has not yet terminated.
+   */
+  [Symbol.iterator]() {
+    this[DISCARDED] = false;
+    let stopped = false;
+    const stop = () => {
+      this.pause();
+      this.off(ERROR, stop);
+      this.off(DESTROYED, stop);
+      this.off("end", stop);
+      stopped = true;
+      return { done: true, value: void 0 };
+    };
+    const next = () => {
+      if (stopped)
+        return stop();
+      const value = this.read();
+      return value === null ? stop() : { done: false, value };
+    };
+    this.once("end", stop);
+    this.once(ERROR, stop);
+    this.once(DESTROYED, stop);
+    return {
+      next,
+      throw: stop,
+      return: stop,
+      [Symbol.iterator]() {
+        return this;
+      }
+    };
+  }
+  /**
+   * Destroy a stream, preventing it from being used for any further purpose.
+   *
+   * If the stream has a `close()` method, then it will be called on
+   * destruction.
+   *
+   * After destruction, any attempt to write data, read data, or emit most
+   * events will be ignored.
+   *
+   * If an error argument is provided, then it will be emitted in an
+   * 'error' event.
+   */
+  destroy(er) {
+    if (this[DESTROYED]) {
+      if (er)
+        this.emit("error", er);
+      else
+        this.emit(DESTROYED);
+      return this;
+    }
+    this[DESTROYED] = true;
+    this[DISCARDED] = true;
+    this[BUFFER].length = 0;
+    this[BUFFERLENGTH] = 0;
+    const wc = this;
+    if (typeof wc.close === "function" && !this[CLOSED])
+      wc.close();
+    if (er)
+      this.emit("error", er);
+    else
+      this.emit(DESTROYED);
+    return this;
+  }
+  /**
+   * Alias for {@link isStream}
+   *
+   * Former export location, maintained for backwards compatibility.
+   *
+   * @deprecated
+   */
+  static get isStream() {
+    return isStream;
+  }
+};
+
+// node_modules/path-scurry/dist/esm/index.js
+var realpathSync = rps.native;
+var defaultFS = {
+  lstatSync,
+  readdir: readdirCB,
+  readdirSync,
+  readlinkSync,
+  realpathSync,
+  promises: {
+    lstat,
+    readdir,
+    readlink,
+    realpath
+  }
+};
+var fsFromOption = (fsOption) => !fsOption || fsOption === defaultFS || fsOption === actualFS ? defaultFS : {
+  ...defaultFS,
+  ...fsOption,
+  promises: {
+    ...defaultFS.promises,
+    ...fsOption.promises || {}
+  }
+};
+var uncDriveRegexp = /^\\\\\?\\([a-z]:)\\?$/i;
+var uncToDrive = (rootPath) => rootPath.replace(/\//g, "\\").replace(uncDriveRegexp, "$1\\");
+var eitherSep = /[\\\/]/;
+var UNKNOWN = 0;
+var IFIFO = 1;
+var IFCHR = 2;
+var IFDIR = 4;
+var IFBLK = 6;
+var IFREG = 8;
+var IFLNK = 10;
+var IFSOCK = 12;
+var IFMT = 15;
+var IFMT_UNKNOWN = ~IFMT;
+var READDIR_CALLED = 16;
+var LSTAT_CALLED = 32;
+var ENOTDIR = 64;
+var ENOENT = 128;
+var ENOREADLINK = 256;
+var ENOREALPATH = 512;
+var ENOCHILD = ENOTDIR | ENOENT | ENOREALPATH;
+var TYPEMASK = 1023;
+var entToType = (s) => s.isFile() ? IFREG : s.isDirectory() ? IFDIR : s.isSymbolicLink() ? IFLNK : s.isCharacterDevice() ? IFCHR : s.isBlockDevice() ? IFBLK : s.isSocket() ? IFSOCK : s.isFIFO() ? IFIFO : UNKNOWN;
+var normalizeCache = /* @__PURE__ */ new Map();
+var normalize = (s) => {
+  const c = normalizeCache.get(s);
+  if (c)
+    return c;
+  const n = s.normalize("NFKD");
+  normalizeCache.set(s, n);
+  return n;
+};
+var normalizeNocaseCache = /* @__PURE__ */ new Map();
+var normalizeNocase = (s) => {
+  const c = normalizeNocaseCache.get(s);
+  if (c)
+    return c;
+  const n = normalize(s.toLowerCase());
+  normalizeNocaseCache.set(s, n);
+  return n;
+};
+var ResolveCache = class extends LRUCache {
+  constructor() {
+    super({ max: 256 });
+  }
+};
+var ChildrenCache = class extends LRUCache {
+  constructor(maxSize = 16 * 1024) {
+    super({
+      maxSize,
+      // parent + children
+      sizeCalculation: (a) => a.length + 1
+    });
+  }
+};
+var setAsCwd = Symbol("PathScurry setAsCwd");
+var PathBase = class {
+  /**
+   * the basename of this path
+   *
+   * **Important**: *always* test the path name against any test string
+   * usingthe {@link isNamed} method, and not by directly comparing this
+   * string. Otherwise, unicode path strings that the system sees as identical
+   * will not be properly treated as the same path, leading to incorrect
+   * behavior and possible security issues.
+   */
+  name;
+  /**
+   * the Path entry corresponding to the path root.
+   *
+   * @internal
+   */
+  root;
+  /**
+   * All roots found within the current PathScurry family
+   *
+   * @internal
+   */
+  roots;
+  /**
+   * a reference to the parent path, or undefined in the case of root entries
+   *
+   * @internal
+   */
+  parent;
+  /**
+   * boolean indicating whether paths are compared case-insensitively
+   * @internal
+   */
+  nocase;
+  // potential default fs override
+  #fs;
+  // Stats fields
+  #dev;
+  get dev() {
+    return this.#dev;
+  }
+  #mode;
+  get mode() {
+    return this.#mode;
+  }
+  #nlink;
+  get nlink() {
+    return this.#nlink;
+  }
+  #uid;
+  get uid() {
+    return this.#uid;
+  }
+  #gid;
+  get gid() {
+    return this.#gid;
+  }
+  #rdev;
+  get rdev() {
+    return this.#rdev;
+  }
+  #blksize;
+  get blksize() {
+    return this.#blksize;
+  }
+  #ino;
+  get ino() {
+    return this.#ino;
+  }
+  #size;
+  get size() {
+    return this.#size;
+  }
+  #blocks;
+  get blocks() {
+    return this.#blocks;
+  }
+  #atimeMs;
+  get atimeMs() {
+    return this.#atimeMs;
+  }
+  #mtimeMs;
+  get mtimeMs() {
+    return this.#mtimeMs;
+  }
+  #ctimeMs;
+  get ctimeMs() {
+    return this.#ctimeMs;
+  }
+  #birthtimeMs;
+  get birthtimeMs() {
+    return this.#birthtimeMs;
+  }
+  #atime;
+  get atime() {
+    return this.#atime;
+  }
+  #mtime;
+  get mtime() {
+    return this.#mtime;
+  }
+  #ctime;
+  get ctime() {
+    return this.#ctime;
+  }
+  #birthtime;
+  get birthtime() {
+    return this.#birthtime;
+  }
+  #matchName;
+  #depth;
+  #fullpath;
+  #fullpathPosix;
+  #relative;
+  #relativePosix;
+  #type;
+  #children;
+  #linkTarget;
+  #realpath;
+  /**
+   * This property is for compatibility with the Dirent class as of
+   * Node v20, where Dirent['path'] refers to the path of the directory
+   * that was passed to readdir.  So, somewhat counterintuitively, this
+   * property refers to the *parent* path, not the path object itself.
+   * For root entries, it's the path to the entry itself.
+   */
+  get path() {
+    return (this.parent || this).fullpath();
+  }
+  /**
+   * Do not create new Path objects directly.  They should always be accessed
+   * via the PathScurry class or other methods on the Path class.
+   *
+   * @internal
+   */
+  constructor(name, type = UNKNOWN, root, roots, nocase, children, opts) {
+    this.name = name;
+    this.#matchName = nocase ? normalizeNocase(name) : normalize(name);
+    this.#type = type & TYPEMASK;
+    this.nocase = nocase;
+    this.roots = roots;
+    this.root = root || this;
+    this.#children = children;
+    this.#fullpath = opts.fullpath;
+    this.#relative = opts.relative;
+    this.#relativePosix = opts.relativePosix;
+    this.parent = opts.parent;
+    if (this.parent) {
+      this.#fs = this.parent.#fs;
+    } else {
+      this.#fs = fsFromOption(opts.fs);
+    }
+  }
+  /**
+   * Returns the depth of the Path object from its root.
+   *
+   * For example, a path at `/foo/bar` would have a depth of 2.
+   */
+  depth() {
+    if (this.#depth !== void 0)
+      return this.#depth;
+    if (!this.parent)
+      return this.#depth = 0;
+    return this.#depth = this.parent.depth() + 1;
+  }
+  /**
+   * @internal
+   */
+  childrenCache() {
+    return this.#children;
+  }
+  /**
+   * Get the Path object referenced by the string path, resolved from this Path
+   */
+  resolve(path4) {
+    if (!path4) {
+      return this;
+    }
+    const rootPath = this.getRootString(path4);
+    const dir = path4.substring(rootPath.length);
+    const dirParts = dir.split(this.splitSep);
+    const result = rootPath ? this.getRoot(rootPath).#resolveParts(dirParts) : this.#resolveParts(dirParts);
+    return result;
+  }
+  #resolveParts(dirParts) {
+    let p = this;
+    for (const part of dirParts) {
+      p = p.child(part);
+    }
+    return p;
+  }
+  /**
+   * Returns the cached children Path objects, if still available.  If they
+   * have fallen out of the cache, then returns an empty array, and resets the
+   * READDIR_CALLED bit, so that future calls to readdir() will require an fs
+   * lookup.
+   *
+   * @internal
+   */
+  children() {
+    const cached = this.#children.get(this);
+    if (cached) {
+      return cached;
+    }
+    const children = Object.assign([], { provisional: 0 });
+    this.#children.set(this, children);
+    this.#type &= ~READDIR_CALLED;
+    return children;
+  }
+  /**
+   * Resolves a path portion and returns or creates the child Path.
+   *
+   * Returns `this` if pathPart is `''` or `'.'`, or `parent` if pathPart is
+   * `'..'`.
+   *
+   * This should not be called directly.  If `pathPart` contains any path
+   * separators, it will lead to unsafe undefined behavior.
+   *
+   * Use `Path.resolve()` instead.
+   *
+   * @internal
+   */
+  child(pathPart, opts) {
+    if (pathPart === "" || pathPart === ".") {
+      return this;
+    }
+    if (pathPart === "..") {
+      return this.parent || this;
+    }
+    const children = this.children();
+    const name = this.nocase ? normalizeNocase(pathPart) : normalize(pathPart);
+    for (const p of children) {
+      if (p.#matchName === name) {
+        return p;
+      }
+    }
+    const s = this.parent ? this.sep : "";
+    const fullpath = this.#fullpath ? this.#fullpath + s + pathPart : void 0;
+    const pchild = this.newChild(pathPart, UNKNOWN, {
+      ...opts,
+      parent: this,
+      fullpath
+    });
+    if (!this.canReaddir()) {
+      pchild.#type |= ENOENT;
+    }
+    children.push(pchild);
+    return pchild;
+  }
+  /**
+   * The relative path from the cwd. If it does not share an ancestor with
+   * the cwd, then this ends up being equivalent to the fullpath()
+   */
+  relative() {
+    if (this.#relative !== void 0) {
+      return this.#relative;
+    }
+    const name = this.name;
+    const p = this.parent;
+    if (!p) {
+      return this.#relative = this.name;
+    }
+    const pv = p.relative();
+    return pv + (!pv || !p.parent ? "" : this.sep) + name;
+  }
+  /**
+   * The relative path from the cwd, using / as the path separator.
+   * If it does not share an ancestor with
+   * the cwd, then this ends up being equivalent to the fullpathPosix()
+   * On posix systems, this is identical to relative().
+   */
+  relativePosix() {
+    if (this.sep === "/")
+      return this.relative();
+    if (this.#relativePosix !== void 0)
+      return this.#relativePosix;
+    const name = this.name;
+    const p = this.parent;
+    if (!p) {
+      return this.#relativePosix = this.fullpathPosix();
+    }
+    const pv = p.relativePosix();
+    return pv + (!pv || !p.parent ? "" : "/") + name;
+  }
+  /**
+   * The fully resolved path string for this Path entry
+   */
+  fullpath() {
+    if (this.#fullpath !== void 0) {
+      return this.#fullpath;
+    }
+    const name = this.name;
+    const p = this.parent;
+    if (!p) {
+      return this.#fullpath = this.name;
+    }
+    const pv = p.fullpath();
+    const fp = pv + (!p.parent ? "" : this.sep) + name;
+    return this.#fullpath = fp;
+  }
+  /**
+   * On platforms other than windows, this is identical to fullpath.
+   *
+   * On windows, this is overridden to return the forward-slash form of the
+   * full UNC path.
+   */
+  fullpathPosix() {
+    if (this.#fullpathPosix !== void 0)
+      return this.#fullpathPosix;
+    if (this.sep === "/")
+      return this.#fullpathPosix = this.fullpath();
+    if (!this.parent) {
+      const p2 = this.fullpath().replace(/\\/g, "/");
+      if (/^[a-z]:\//i.test(p2)) {
+        return this.#fullpathPosix = `//?/${p2}`;
+      } else {
+        return this.#fullpathPosix = p2;
+      }
+    }
+    const p = this.parent;
+    const pfpp = p.fullpathPosix();
+    const fpp = pfpp + (!pfpp || !p.parent ? "" : "/") + this.name;
+    return this.#fullpathPosix = fpp;
+  }
+  /**
+   * Is the Path of an unknown type?
+   *
+   * Note that we might know *something* about it if there has been a previous
+   * filesystem operation, for example that it does not exist, or is not a
+   * link, or whether it has child entries.
+   */
+  isUnknown() {
+    return (this.#type & IFMT) === UNKNOWN;
+  }
+  isType(type) {
+    return this[`is${type}`]();
+  }
+  getType() {
+    return this.isUnknown() ? "Unknown" : this.isDirectory() ? "Directory" : this.isFile() ? "File" : this.isSymbolicLink() ? "SymbolicLink" : this.isFIFO() ? "FIFO" : this.isCharacterDevice() ? "CharacterDevice" : this.isBlockDevice() ? "BlockDevice" : (
+      /* c8 ignore start */
+      this.isSocket() ? "Socket" : "Unknown"
+    );
+  }
+  /**
+   * Is the Path a regular file?
+   */
+  isFile() {
+    return (this.#type & IFMT) === IFREG;
+  }
+  /**
+   * Is the Path a directory?
+   */
+  isDirectory() {
+    return (this.#type & IFMT) === IFDIR;
+  }
+  /**
+   * Is the path a character device?
+   */
+  isCharacterDevice() {
+    return (this.#type & IFMT) === IFCHR;
+  }
+  /**
+   * Is the path a block device?
+   */
+  isBlockDevice() {
+    return (this.#type & IFMT) === IFBLK;
+  }
+  /**
+   * Is the path a FIFO pipe?
+   */
+  isFIFO() {
+    return (this.#type & IFMT) === IFIFO;
+  }
+  /**
+   * Is the path a socket?
+   */
+  isSocket() {
+    return (this.#type & IFMT) === IFSOCK;
+  }
+  /**
+   * Is the path a symbolic link?
+   */
+  isSymbolicLink() {
+    return (this.#type & IFLNK) === IFLNK;
+  }
+  /**
+   * Return the entry if it has been subject of a successful lstat, or
+   * undefined otherwise.
+   *
+   * Does not read the filesystem, so an undefined result *could* simply
+   * mean that we haven't called lstat on it.
+   */
+  lstatCached() {
+    return this.#type & LSTAT_CALLED ? this : void 0;
+  }
+  /**
+   * Return the cached link target if the entry has been the subject of a
+   * successful readlink, or undefined otherwise.
+   *
+   * Does not read the filesystem, so an undefined result *could* just mean we
+   * don't have any cached data. Only use it if you are very sure that a
+   * readlink() has been called at some point.
+   */
+  readlinkCached() {
+    return this.#linkTarget;
+  }
+  /**
+   * Returns the cached realpath target if the entry has been the subject
+   * of a successful realpath, or undefined otherwise.
+   *
+   * Does not read the filesystem, so an undefined result *could* just mean we
+   * don't have any cached data. Only use it if you are very sure that a
+   * realpath() has been called at some point.
+   */
+  realpathCached() {
+    return this.#realpath;
+  }
+  /**
+   * Returns the cached child Path entries array if the entry has been the
+   * subject of a successful readdir(), or [] otherwise.
+   *
+   * Does not read the filesystem, so an empty array *could* just mean we
+   * don't have any cached data. Only use it if you are very sure that a
+   * readdir() has been called recently enough to still be valid.
+   */
+  readdirCached() {
+    const children = this.children();
+    return children.slice(0, children.provisional);
+  }
+  /**
+   * Return true if it's worth trying to readlink.  Ie, we don't (yet) have
+   * any indication that readlink will definitely fail.
+   *
+   * Returns false if the path is known to not be a symlink, if a previous
+   * readlink failed, or if the entry does not exist.
+   */
+  canReadlink() {
+    if (this.#linkTarget)
+      return true;
+    if (!this.parent)
+      return false;
+    const ifmt = this.#type & IFMT;
+    return !(ifmt !== UNKNOWN && ifmt !== IFLNK || this.#type & ENOREADLINK || this.#type & ENOENT);
+  }
+  /**
+   * Return true if readdir has previously been successfully called on this
+   * path, indicating that cachedReaddir() is likely valid.
+   */
+  calledReaddir() {
+    return !!(this.#type & READDIR_CALLED);
+  }
+  /**
+   * Returns true if the path is known to not exist. That is, a previous lstat
+   * or readdir failed to verify its existence when that would have been
+   * expected, or a parent entry was marked either enoent or enotdir.
+   */
+  isENOENT() {
+    return !!(this.#type & ENOENT);
+  }
+  /**
+   * Return true if the path is a match for the given path name.  This handles
+   * case sensitivity and unicode normalization.
+   *
+   * Note: even on case-sensitive systems, it is **not** safe to test the
+   * equality of the `.name` property to determine whether a given pathname
+   * matches, due to unicode normalization mismatches.
+   *
+   * Always use this method instead of testing the `path.name` property
+   * directly.
+   */
+  isNamed(n) {
+    return !this.nocase ? this.#matchName === normalize(n) : this.#matchName === normalizeNocase(n);
+  }
+  /**
+   * Return the Path object corresponding to the target of a symbolic link.
+   *
+   * If the Path is not a symbolic link, or if the readlink call fails for any
+   * reason, `undefined` is returned.
+   *
+   * Result is cached, and thus may be outdated if the filesystem is mutated.
+   */
+  async readlink() {
+    const target = this.#linkTarget;
+    if (target) {
+      return target;
+    }
+    if (!this.canReadlink()) {
+      return void 0;
+    }
+    if (!this.parent) {
+      return void 0;
+    }
+    try {
+      const read = await this.#fs.promises.readlink(this.fullpath());
+      const linkTarget = (await this.parent.realpath())?.resolve(read);
+      if (linkTarget) {
+        return this.#linkTarget = linkTarget;
+      }
+    } catch (er) {
+      this.#readlinkFail(er.code);
+      return void 0;
+    }
+  }
+  /**
+   * Synchronous {@link PathBase.readlink}
+   */
+  readlinkSync() {
+    const target = this.#linkTarget;
+    if (target) {
+      return target;
+    }
+    if (!this.canReadlink()) {
+      return void 0;
+    }
+    if (!this.parent) {
+      return void 0;
+    }
+    try {
+      const read = this.#fs.readlinkSync(this.fullpath());
+      const linkTarget = this.parent.realpathSync()?.resolve(read);
+      if (linkTarget) {
+        return this.#linkTarget = linkTarget;
+      }
+    } catch (er) {
+      this.#readlinkFail(er.code);
+      return void 0;
+    }
+  }
+  #readdirSuccess(children) {
+    this.#type |= READDIR_CALLED;
+    for (let p = children.provisional; p < children.length; p++) {
+      const c = children[p];
+      if (c)
+        c.#markENOENT();
+    }
+  }
+  #markENOENT() {
+    if (this.#type & ENOENT)
+      return;
+    this.#type = (this.#type | ENOENT) & IFMT_UNKNOWN;
+    this.#markChildrenENOENT();
+  }
+  #markChildrenENOENT() {
+    const children = this.children();
+    children.provisional = 0;
+    for (const p of children) {
+      p.#markENOENT();
+    }
+  }
+  #markENOREALPATH() {
+    this.#type |= ENOREALPATH;
+    this.#markENOTDIR();
+  }
+  // save the information when we know the entry is not a dir
+  #markENOTDIR() {
+    if (this.#type & ENOTDIR)
+      return;
+    let t = this.#type;
+    if ((t & IFMT) === IFDIR)
+      t &= IFMT_UNKNOWN;
+    this.#type = t | ENOTDIR;
+    this.#markChildrenENOENT();
+  }
+  #readdirFail(code = "") {
+    if (code === "ENOTDIR" || code === "EPERM") {
+      this.#markENOTDIR();
+    } else if (code === "ENOENT") {
+      this.#markENOENT();
+    } else {
+      this.children().provisional = 0;
+    }
+  }
+  #lstatFail(code = "") {
+    if (code === "ENOTDIR") {
+      const p = this.parent;
+      p.#markENOTDIR();
+    } else if (code === "ENOENT") {
+      this.#markENOENT();
+    }
+  }
+  #readlinkFail(code = "") {
+    let ter = this.#type;
+    ter |= ENOREADLINK;
+    if (code === "ENOENT")
+      ter |= ENOENT;
+    if (code === "EINVAL" || code === "UNKNOWN") {
+      ter &= IFMT_UNKNOWN;
+    }
+    this.#type = ter;
+    if (code === "ENOTDIR" && this.parent) {
+      this.parent.#markENOTDIR();
+    }
+  }
+  #readdirAddChild(e, c) {
+    return this.#readdirMaybePromoteChild(e, c) || this.#readdirAddNewChild(e, c);
+  }
+  #readdirAddNewChild(e, c) {
+    const type = entToType(e);
+    const child = this.newChild(e.name, type, { parent: this });
+    const ifmt = child.#type & IFMT;
+    if (ifmt !== IFDIR && ifmt !== IFLNK && ifmt !== UNKNOWN) {
+      child.#type |= ENOTDIR;
+    }
+    c.unshift(child);
+    c.provisional++;
+    return child;
+  }
+  #readdirMaybePromoteChild(e, c) {
+    for (let p = c.provisional; p < c.length; p++) {
+      const pchild = c[p];
+      const name = this.nocase ? normalizeNocase(e.name) : normalize(e.name);
+      if (name !== pchild.#matchName) {
+        continue;
+      }
+      return this.#readdirPromoteChild(e, pchild, p, c);
+    }
+  }
+  #readdirPromoteChild(e, p, index, c) {
+    const v = p.name;
+    p.#type = p.#type & IFMT_UNKNOWN | entToType(e);
+    if (v !== e.name)
+      p.name = e.name;
+    if (index !== c.provisional) {
+      if (index === c.length - 1)
+        c.pop();
+      else
+        c.splice(index, 1);
+      c.unshift(p);
+    }
+    c.provisional++;
+    return p;
+  }
+  /**
+   * Call lstat() on this Path, and update all known information that can be
+   * determined.
+   *
+   * Note that unlike `fs.lstat()`, the returned value does not contain some
+   * information, such as `mode`, `dev`, `nlink`, and `ino`.  If that
+   * information is required, you will need to call `fs.lstat` yourself.
+   *
+   * If the Path refers to a nonexistent file, or if the lstat call fails for
+   * any reason, `undefined` is returned.  Otherwise the updated Path object is
+   * returned.
+   *
+   * Results are cached, and thus may be out of date if the filesystem is
+   * mutated.
+   */
+  async lstat() {
+    if ((this.#type & ENOENT) === 0) {
+      try {
+        this.#applyStat(await this.#fs.promises.lstat(this.fullpath()));
+        return this;
+      } catch (er) {
+        this.#lstatFail(er.code);
+      }
+    }
+  }
+  /**
+   * synchronous {@link PathBase.lstat}
+   */
+  lstatSync() {
+    if ((this.#type & ENOENT) === 0) {
+      try {
+        this.#applyStat(this.#fs.lstatSync(this.fullpath()));
+        return this;
+      } catch (er) {
+        this.#lstatFail(er.code);
+      }
+    }
+  }
+  #applyStat(st) {
+    const { atime, atimeMs, birthtime, birthtimeMs, blksize, blocks: blocks2, ctime, ctimeMs, dev, gid, ino, mode, mtime, mtimeMs, nlink, rdev, size, uid } = st;
+    this.#atime = atime;
+    this.#atimeMs = atimeMs;
+    this.#birthtime = birthtime;
+    this.#birthtimeMs = birthtimeMs;
+    this.#blksize = blksize;
+    this.#blocks = blocks2;
+    this.#ctime = ctime;
+    this.#ctimeMs = ctimeMs;
+    this.#dev = dev;
+    this.#gid = gid;
+    this.#ino = ino;
+    this.#mode = mode;
+    this.#mtime = mtime;
+    this.#mtimeMs = mtimeMs;
+    this.#nlink = nlink;
+    this.#rdev = rdev;
+    this.#size = size;
+    this.#uid = uid;
+    const ifmt = entToType(st);
+    this.#type = this.#type & IFMT_UNKNOWN | ifmt | LSTAT_CALLED;
+    if (ifmt !== UNKNOWN && ifmt !== IFDIR && ifmt !== IFLNK) {
+      this.#type |= ENOTDIR;
+    }
+  }
+  #onReaddirCB = [];
+  #readdirCBInFlight = false;
+  #callOnReaddirCB(children) {
+    this.#readdirCBInFlight = false;
+    const cbs = this.#onReaddirCB.slice();
+    this.#onReaddirCB.length = 0;
+    cbs.forEach((cb) => cb(null, children));
+  }
+  /**
+   * Standard node-style callback interface to get list of directory entries.
+   *
+   * If the Path cannot or does not contain any children, then an empty array
+   * is returned.
+   *
+   * Results are cached, and thus may be out of date if the filesystem is
+   * mutated.
+   *
+   * @param cb The callback called with (er, entries).  Note that the `er`
+   * param is somewhat extraneous, as all readdir() errors are handled and
+   * simply result in an empty set of entries being returned.
+   * @param allowZalgo Boolean indicating that immediately known results should
+   * *not* be deferred with `queueMicrotask`. Defaults to `false`. Release
+   * zalgo at your peril, the dark pony lord is devious and unforgiving.
+   */
+  readdirCB(cb, allowZalgo = false) {
+    if (!this.canReaddir()) {
+      if (allowZalgo)
+        cb(null, []);
+      else
+        queueMicrotask(() => cb(null, []));
+      return;
+    }
+    const children = this.children();
+    if (this.calledReaddir()) {
+      const c = children.slice(0, children.provisional);
+      if (allowZalgo)
+        cb(null, c);
+      else
+        queueMicrotask(() => cb(null, c));
+      return;
+    }
+    this.#onReaddirCB.push(cb);
+    if (this.#readdirCBInFlight) {
+      return;
+    }
+    this.#readdirCBInFlight = true;
+    const fullpath = this.fullpath();
+    this.#fs.readdir(fullpath, { withFileTypes: true }, (er, entries) => {
+      if (er) {
+        this.#readdirFail(er.code);
+        children.provisional = 0;
+      } else {
+        for (const e of entries) {
+          this.#readdirAddChild(e, children);
+        }
+        this.#readdirSuccess(children);
+      }
+      this.#callOnReaddirCB(children.slice(0, children.provisional));
+      return;
+    });
+  }
+  #asyncReaddirInFlight;
+  /**
+   * Return an array of known child entries.
+   *
+   * If the Path cannot or does not contain any children, then an empty array
+   * is returned.
+   *
+   * Results are cached, and thus may be out of date if the filesystem is
+   * mutated.
+   */
+  async readdir() {
+    if (!this.canReaddir()) {
+      return [];
+    }
+    const children = this.children();
+    if (this.calledReaddir()) {
+      return children.slice(0, children.provisional);
+    }
+    const fullpath = this.fullpath();
+    if (this.#asyncReaddirInFlight) {
+      await this.#asyncReaddirInFlight;
+    } else {
+      let resolve = () => {
+      };
+      this.#asyncReaddirInFlight = new Promise((res) => resolve = res);
+      try {
+        for (const e of await this.#fs.promises.readdir(fullpath, {
+          withFileTypes: true
+        })) {
+          this.#readdirAddChild(e, children);
+        }
+        this.#readdirSuccess(children);
+      } catch (er) {
+        this.#readdirFail(er.code);
+        children.provisional = 0;
+      }
+      this.#asyncReaddirInFlight = void 0;
+      resolve();
+    }
+    return children.slice(0, children.provisional);
+  }
+  /**
+   * synchronous {@link PathBase.readdir}
+   */
+  readdirSync() {
+    if (!this.canReaddir()) {
+      return [];
+    }
+    const children = this.children();
+    if (this.calledReaddir()) {
+      return children.slice(0, children.provisional);
+    }
+    const fullpath = this.fullpath();
+    try {
+      for (const e of this.#fs.readdirSync(fullpath, {
+        withFileTypes: true
+      })) {
+        this.#readdirAddChild(e, children);
+      }
+      this.#readdirSuccess(children);
+    } catch (er) {
+      this.#readdirFail(er.code);
+      children.provisional = 0;
+    }
+    return children.slice(0, children.provisional);
+  }
+  canReaddir() {
+    if (this.#type & ENOCHILD)
+      return false;
+    const ifmt = IFMT & this.#type;
+    if (!(ifmt === UNKNOWN || ifmt === IFDIR || ifmt === IFLNK)) {
+      return false;
+    }
+    return true;
+  }
+  shouldWalk(dirs, walkFilter) {
+    return (this.#type & IFDIR) === IFDIR && !(this.#type & ENOCHILD) && !dirs.has(this) && (!walkFilter || walkFilter(this));
+  }
+  /**
+   * Return the Path object corresponding to path as resolved
+   * by realpath(3).
+   *
+   * If the realpath call fails for any reason, `undefined` is returned.
+   *
+   * Result is cached, and thus may be outdated if the filesystem is mutated.
+   * On success, returns a Path object.
+   */
+  async realpath() {
+    if (this.#realpath)
+      return this.#realpath;
+    if ((ENOREALPATH | ENOREADLINK | ENOENT) & this.#type)
+      return void 0;
+    try {
+      const rp = await this.#fs.promises.realpath(this.fullpath());
+      return this.#realpath = this.resolve(rp);
+    } catch (_) {
+      this.#markENOREALPATH();
+    }
+  }
+  /**
+   * Synchronous {@link realpath}
+   */
+  realpathSync() {
+    if (this.#realpath)
+      return this.#realpath;
+    if ((ENOREALPATH | ENOREADLINK | ENOENT) & this.#type)
+      return void 0;
+    try {
+      const rp = this.#fs.realpathSync(this.fullpath());
+      return this.#realpath = this.resolve(rp);
+    } catch (_) {
+      this.#markENOREALPATH();
+    }
+  }
+  /**
+   * Internal method to mark this Path object as the scurry cwd,
+   * called by {@link PathScurry#chdir}
+   *
+   * @internal
+   */
+  [setAsCwd](oldCwd) {
+    if (oldCwd === this)
+      return;
+    const changed = /* @__PURE__ */ new Set([]);
+    let rp = [];
+    let p = this;
+    while (p && p.parent) {
+      changed.add(p);
+      p.#relative = rp.join(this.sep);
+      p.#relativePosix = rp.join("/");
+      p = p.parent;
+      rp.push("..");
+    }
+    p = oldCwd;
+    while (p && p.parent && !changed.has(p)) {
+      p.#relative = void 0;
+      p.#relativePosix = void 0;
+      p = p.parent;
+    }
+  }
+};
+var PathWin32 = class _PathWin32 extends PathBase {
+  /**
+   * Separator for generating path strings.
+   */
+  sep = "\\";
+  /**
+   * Separator for parsing path strings.
+   */
+  splitSep = eitherSep;
+  /**
+   * Do not create new Path objects directly.  They should always be accessed
+   * via the PathScurry class or other methods on the Path class.
+   *
+   * @internal
+   */
+  constructor(name, type = UNKNOWN, root, roots, nocase, children, opts) {
+    super(name, type, root, roots, nocase, children, opts);
+  }
+  /**
+   * @internal
+   */
+  newChild(name, type = UNKNOWN, opts = {}) {
+    return new _PathWin32(name, type, this.root, this.roots, this.nocase, this.childrenCache(), opts);
+  }
+  /**
+   * @internal
+   */
+  getRootString(path4) {
+    return win32.parse(path4).root;
+  }
+  /**
+   * @internal
+   */
+  getRoot(rootPath) {
+    rootPath = uncToDrive(rootPath.toUpperCase());
+    if (rootPath === this.root.name) {
+      return this.root;
+    }
+    for (const [compare2, root] of Object.entries(this.roots)) {
+      if (this.sameRoot(rootPath, compare2)) {
+        return this.roots[rootPath] = root;
+      }
+    }
+    return this.roots[rootPath] = new PathScurryWin32(rootPath, this).root;
+  }
+  /**
+   * @internal
+   */
+  sameRoot(rootPath, compare2 = this.root.name) {
+    rootPath = rootPath.toUpperCase().replace(/\//g, "\\").replace(uncDriveRegexp, "$1\\");
+    return rootPath === compare2;
+  }
+};
+var PathPosix = class _PathPosix extends PathBase {
+  /**
+   * separator for parsing path strings
+   */
+  splitSep = "/";
+  /**
+   * separator for generating path strings
+   */
+  sep = "/";
+  /**
+   * Do not create new Path objects directly.  They should always be accessed
+   * via the PathScurry class or other methods on the Path class.
+   *
+   * @internal
+   */
+  constructor(name, type = UNKNOWN, root, roots, nocase, children, opts) {
+    super(name, type, root, roots, nocase, children, opts);
+  }
+  /**
+   * @internal
+   */
+  getRootString(path4) {
+    return path4.startsWith("/") ? "/" : "";
+  }
+  /**
+   * @internal
+   */
+  getRoot(_rootPath) {
+    return this.root;
+  }
+  /**
+   * @internal
+   */
+  newChild(name, type = UNKNOWN, opts = {}) {
+    return new _PathPosix(name, type, this.root, this.roots, this.nocase, this.childrenCache(), opts);
+  }
+};
+var PathScurryBase = class {
+  /**
+   * The root Path entry for the current working directory of this Scurry
+   */
+  root;
+  /**
+   * The string path for the root of this Scurry's current working directory
+   */
+  rootPath;
+  /**
+   * A collection of all roots encountered, referenced by rootPath
+   */
+  roots;
+  /**
+   * The Path entry corresponding to this PathScurry's current working directory.
+   */
+  cwd;
+  #resolveCache;
+  #resolvePosixCache;
+  #children;
+  /**
+   * Perform path comparisons case-insensitively.
+   *
+   * Defaults true on Darwin and Windows systems, false elsewhere.
+   */
+  nocase;
+  #fs;
+  /**
+   * This class should not be instantiated directly.
+   *
+   * Use PathScurryWin32, PathScurryDarwin, PathScurryPosix, or PathScurry
+   *
+   * @internal
+   */
+  constructor(cwd = process.cwd(), pathImpl, sep2, { nocase, childrenCacheSize = 16 * 1024, fs: fs4 = defaultFS } = {}) {
+    this.#fs = fsFromOption(fs4);
+    if (cwd instanceof URL || cwd.startsWith("file://")) {
+      cwd = fileURLToPath(cwd);
+    }
+    const cwdPath = pathImpl.resolve(cwd);
+    this.roots = /* @__PURE__ */ Object.create(null);
+    this.rootPath = this.parseRootPath(cwdPath);
+    this.#resolveCache = new ResolveCache();
+    this.#resolvePosixCache = new ResolveCache();
+    this.#children = new ChildrenCache(childrenCacheSize);
+    const split = cwdPath.substring(this.rootPath.length).split(sep2);
+    if (split.length === 1 && !split[0]) {
+      split.pop();
+    }
+    if (nocase === void 0) {
+      throw new TypeError("must provide nocase setting to PathScurryBase ctor");
+    }
+    this.nocase = nocase;
+    this.root = this.newRoot(this.#fs);
+    this.roots[this.rootPath] = this.root;
+    let prev = this.root;
+    let len = split.length - 1;
+    const joinSep = pathImpl.sep;
+    let abs = this.rootPath;
+    let sawFirst = false;
+    for (const part of split) {
+      const l = len--;
+      prev = prev.child(part, {
+        relative: new Array(l).fill("..").join(joinSep),
+        relativePosix: new Array(l).fill("..").join("/"),
+        fullpath: abs += (sawFirst ? "" : joinSep) + part
+      });
+      sawFirst = true;
+    }
+    this.cwd = prev;
+  }
+  /**
+   * Get the depth of a provided path, string, or the cwd
+   */
+  depth(path4 = this.cwd) {
+    if (typeof path4 === "string") {
+      path4 = this.cwd.resolve(path4);
+    }
+    return path4.depth();
+  }
+  /**
+   * Return the cache of child entries.  Exposed so subclasses can create
+   * child Path objects in a platform-specific way.
+   *
+   * @internal
+   */
+  childrenCache() {
+    return this.#children;
+  }
+  /**
+   * Resolve one or more path strings to a resolved string
+   *
+   * Same interface as require('path').resolve.
+   *
+   * Much faster than path.resolve() when called multiple times for the same
+   * path, because the resolved Path objects are cached.  Much slower
+   * otherwise.
+   */
+  resolve(...paths) {
+    let r = "";
+    for (let i = paths.length - 1; i >= 0; i--) {
+      const p = paths[i];
+      if (!p || p === ".")
+        continue;
+      r = r ? `${p}/${r}` : p;
+      if (this.isAbsolute(p)) {
+        break;
+      }
+    }
+    const cached = this.#resolveCache.get(r);
+    if (cached !== void 0) {
+      return cached;
+    }
+    const result = this.cwd.resolve(r).fullpath();
+    this.#resolveCache.set(r, result);
+    return result;
+  }
+  /**
+   * Resolve one or more path strings to a resolved string, returning
+   * the posix path.  Identical to .resolve() on posix systems, but on
+   * windows will return a forward-slash separated UNC path.
+   *
+   * Same interface as require('path').resolve.
+   *
+   * Much faster than path.resolve() when called multiple times for the same
+   * path, because the resolved Path objects are cached.  Much slower
+   * otherwise.
+   */
+  resolvePosix(...paths) {
+    let r = "";
+    for (let i = paths.length - 1; i >= 0; i--) {
+      const p = paths[i];
+      if (!p || p === ".")
+        continue;
+      r = r ? `${p}/${r}` : p;
+      if (this.isAbsolute(p)) {
+        break;
+      }
+    }
+    const cached = this.#resolvePosixCache.get(r);
+    if (cached !== void 0) {
+      return cached;
+    }
+    const result = this.cwd.resolve(r).fullpathPosix();
+    this.#resolvePosixCache.set(r, result);
+    return result;
+  }
+  /**
+   * find the relative path from the cwd to the supplied path string or entry
+   */
+  relative(entry = this.cwd) {
+    if (typeof entry === "string") {
+      entry = this.cwd.resolve(entry);
+    }
+    return entry.relative();
+  }
+  /**
+   * find the relative path from the cwd to the supplied path string or
+   * entry, using / as the path delimiter, even on Windows.
+   */
+  relativePosix(entry = this.cwd) {
+    if (typeof entry === "string") {
+      entry = this.cwd.resolve(entry);
+    }
+    return entry.relativePosix();
+  }
+  /**
+   * Return the basename for the provided string or Path object
+   */
+  basename(entry = this.cwd) {
+    if (typeof entry === "string") {
+      entry = this.cwd.resolve(entry);
+    }
+    return entry.name;
+  }
+  /**
+   * Return the dirname for the provided string or Path object
+   */
+  dirname(entry = this.cwd) {
+    if (typeof entry === "string") {
+      entry = this.cwd.resolve(entry);
+    }
+    return (entry.parent || entry).fullpath();
+  }
+  async readdir(entry = this.cwd, opts = {
+    withFileTypes: true
+  }) {
+    if (typeof entry === "string") {
+      entry = this.cwd.resolve(entry);
+    } else if (!(entry instanceof PathBase)) {
+      opts = entry;
+      entry = this.cwd;
+    }
+    const { withFileTypes } = opts;
+    if (!entry.canReaddir()) {
+      return [];
+    } else {
+      const p = await entry.readdir();
+      return withFileTypes ? p : p.map((e) => e.name);
+    }
+  }
+  readdirSync(entry = this.cwd, opts = {
+    withFileTypes: true
+  }) {
+    if (typeof entry === "string") {
+      entry = this.cwd.resolve(entry);
+    } else if (!(entry instanceof PathBase)) {
+      opts = entry;
+      entry = this.cwd;
+    }
+    const { withFileTypes = true } = opts;
+    if (!entry.canReaddir()) {
+      return [];
+    } else if (withFileTypes) {
+      return entry.readdirSync();
+    } else {
+      return entry.readdirSync().map((e) => e.name);
+    }
+  }
+  /**
+   * Call lstat() on the string or Path object, and update all known
+   * information that can be determined.
+   *
+   * Note that unlike `fs.lstat()`, the returned value does not contain some
+   * information, such as `mode`, `dev`, `nlink`, and `ino`.  If that
+   * information is required, you will need to call `fs.lstat` yourself.
+   *
+   * If the Path refers to a nonexistent file, or if the lstat call fails for
+   * any reason, `undefined` is returned.  Otherwise the updated Path object is
+   * returned.
+   *
+   * Results are cached, and thus may be out of date if the filesystem is
+   * mutated.
+   */
+  async lstat(entry = this.cwd) {
+    if (typeof entry === "string") {
+      entry = this.cwd.resolve(entry);
+    }
+    return entry.lstat();
+  }
+  /**
+   * synchronous {@link PathScurryBase.lstat}
+   */
+  lstatSync(entry = this.cwd) {
+    if (typeof entry === "string") {
+      entry = this.cwd.resolve(entry);
+    }
+    return entry.lstatSync();
+  }
+  async readlink(entry = this.cwd, { withFileTypes } = {
+    withFileTypes: false
+  }) {
+    if (typeof entry === "string") {
+      entry = this.cwd.resolve(entry);
+    } else if (!(entry instanceof PathBase)) {
+      withFileTypes = entry.withFileTypes;
+      entry = this.cwd;
+    }
+    const e = await entry.readlink();
+    return withFileTypes ? e : e?.fullpath();
+  }
+  readlinkSync(entry = this.cwd, { withFileTypes } = {
+    withFileTypes: false
+  }) {
+    if (typeof entry === "string") {
+      entry = this.cwd.resolve(entry);
+    } else if (!(entry instanceof PathBase)) {
+      withFileTypes = entry.withFileTypes;
+      entry = this.cwd;
+    }
+    const e = entry.readlinkSync();
+    return withFileTypes ? e : e?.fullpath();
+  }
+  async realpath(entry = this.cwd, { withFileTypes } = {
+    withFileTypes: false
+  }) {
+    if (typeof entry === "string") {
+      entry = this.cwd.resolve(entry);
+    } else if (!(entry instanceof PathBase)) {
+      withFileTypes = entry.withFileTypes;
+      entry = this.cwd;
+    }
+    const e = await entry.realpath();
+    return withFileTypes ? e : e?.fullpath();
+  }
+  realpathSync(entry = this.cwd, { withFileTypes } = {
+    withFileTypes: false
+  }) {
+    if (typeof entry === "string") {
+      entry = this.cwd.resolve(entry);
+    } else if (!(entry instanceof PathBase)) {
+      withFileTypes = entry.withFileTypes;
+      entry = this.cwd;
+    }
+    const e = entry.realpathSync();
+    return withFileTypes ? e : e?.fullpath();
+  }
+  async walk(entry = this.cwd, opts = {}) {
+    if (typeof entry === "string") {
+      entry = this.cwd.resolve(entry);
+    } else if (!(entry instanceof PathBase)) {
+      opts = entry;
+      entry = this.cwd;
+    }
+    const { withFileTypes = true, follow = false, filter: filter2, walkFilter } = opts;
+    const results = [];
+    if (!filter2 || filter2(entry)) {
+      results.push(withFileTypes ? entry : entry.fullpath());
+    }
+    const dirs = /* @__PURE__ */ new Set();
+    const walk = (dir, cb) => {
+      dirs.add(dir);
+      dir.readdirCB((er, entries) => {
+        if (er) {
+          return cb(er);
+        }
+        let len = entries.length;
+        if (!len)
+          return cb();
+        const next = () => {
+          if (--len === 0) {
+            cb();
+          }
+        };
+        for (const e of entries) {
+          if (!filter2 || filter2(e)) {
+            results.push(withFileTypes ? e : e.fullpath());
+          }
+          if (follow && e.isSymbolicLink()) {
+            e.realpath().then((r) => r?.isUnknown() ? r.lstat() : r).then((r) => r?.shouldWalk(dirs, walkFilter) ? walk(r, next) : next());
+          } else {
+            if (e.shouldWalk(dirs, walkFilter)) {
+              walk(e, next);
+            } else {
+              next();
+            }
+          }
+        }
+      }, true);
+    };
+    const start = entry;
+    return new Promise((res, rej) => {
+      walk(start, (er) => {
+        if (er)
+          return rej(er);
+        res(results);
+      });
+    });
+  }
+  walkSync(entry = this.cwd, opts = {}) {
+    if (typeof entry === "string") {
+      entry = this.cwd.resolve(entry);
+    } else if (!(entry instanceof PathBase)) {
+      opts = entry;
+      entry = this.cwd;
+    }
+    const { withFileTypes = true, follow = false, filter: filter2, walkFilter } = opts;
+    const results = [];
+    if (!filter2 || filter2(entry)) {
+      results.push(withFileTypes ? entry : entry.fullpath());
+    }
+    const dirs = /* @__PURE__ */ new Set([entry]);
+    for (const dir of dirs) {
+      const entries = dir.readdirSync();
+      for (const e of entries) {
+        if (!filter2 || filter2(e)) {
+          results.push(withFileTypes ? e : e.fullpath());
+        }
+        let r = e;
+        if (e.isSymbolicLink()) {
+          if (!(follow && (r = e.realpathSync())))
+            continue;
+          if (r.isUnknown())
+            r.lstatSync();
+        }
+        if (r.shouldWalk(dirs, walkFilter)) {
+          dirs.add(r);
+        }
+      }
+    }
+    return results;
+  }
+  /**
+   * Support for `for await`
+   *
+   * Alias for {@link PathScurryBase.iterate}
+   *
+   * Note: As of Node 19, this is very slow, compared to other methods of
+   * walking.  Consider using {@link PathScurryBase.stream} if memory overhead
+   * and backpressure are concerns, or {@link PathScurryBase.walk} if not.
+   */
+  [Symbol.asyncIterator]() {
+    return this.iterate();
+  }
+  iterate(entry = this.cwd, options = {}) {
+    if (typeof entry === "string") {
+      entry = this.cwd.resolve(entry);
+    } else if (!(entry instanceof PathBase)) {
+      options = entry;
+      entry = this.cwd;
+    }
+    return this.stream(entry, options)[Symbol.asyncIterator]();
+  }
+  /**
+   * Iterating over a PathScurry performs a synchronous walk.
+   *
+   * Alias for {@link PathScurryBase.iterateSync}
+   */
+  [Symbol.iterator]() {
+    return this.iterateSync();
+  }
+  *iterateSync(entry = this.cwd, opts = {}) {
+    if (typeof entry === "string") {
+      entry = this.cwd.resolve(entry);
+    } else if (!(entry instanceof PathBase)) {
+      opts = entry;
+      entry = this.cwd;
+    }
+    const { withFileTypes = true, follow = false, filter: filter2, walkFilter } = opts;
+    if (!filter2 || filter2(entry)) {
+      yield withFileTypes ? entry : entry.fullpath();
+    }
+    const dirs = /* @__PURE__ */ new Set([entry]);
+    for (const dir of dirs) {
+      const entries = dir.readdirSync();
+      for (const e of entries) {
+        if (!filter2 || filter2(e)) {
+          yield withFileTypes ? e : e.fullpath();
+        }
+        let r = e;
+        if (e.isSymbolicLink()) {
+          if (!(follow && (r = e.realpathSync())))
+            continue;
+          if (r.isUnknown())
+            r.lstatSync();
+        }
+        if (r.shouldWalk(dirs, walkFilter)) {
+          dirs.add(r);
+        }
+      }
+    }
+  }
+  stream(entry = this.cwd, opts = {}) {
+    if (typeof entry === "string") {
+      entry = this.cwd.resolve(entry);
+    } else if (!(entry instanceof PathBase)) {
+      opts = entry;
+      entry = this.cwd;
+    }
+    const { withFileTypes = true, follow = false, filter: filter2, walkFilter } = opts;
+    const results = new Minipass({ objectMode: true });
+    if (!filter2 || filter2(entry)) {
+      results.write(withFileTypes ? entry : entry.fullpath());
+    }
+    const dirs = /* @__PURE__ */ new Set();
+    const queue = [entry];
+    let processing = 0;
+    const process3 = () => {
+      let paused = false;
+      while (!paused) {
+        const dir = queue.shift();
+        if (!dir) {
+          if (processing === 0)
+            results.end();
+          return;
+        }
+        processing++;
+        dirs.add(dir);
+        const onReaddir = (er, entries, didRealpaths = false) => {
+          if (er)
+            return results.emit("error", er);
+          if (follow && !didRealpaths) {
+            const promises = [];
+            for (const e of entries) {
+              if (e.isSymbolicLink()) {
+                promises.push(e.realpath().then((r) => r?.isUnknown() ? r.lstat() : r));
+              }
+            }
+            if (promises.length) {
+              Promise.all(promises).then(() => onReaddir(null, entries, true));
+              return;
+            }
+          }
+          for (const e of entries) {
+            if (e && (!filter2 || filter2(e))) {
+              if (!results.write(withFileTypes ? e : e.fullpath())) {
+                paused = true;
+              }
+            }
+          }
+          processing--;
+          for (const e of entries) {
+            const r = e.realpathCached() || e;
+            if (r.shouldWalk(dirs, walkFilter)) {
+              queue.push(r);
+            }
+          }
+          if (paused && !results.flowing) {
+            results.once("drain", process3);
+          } else if (!sync2) {
+            process3();
+          }
+        };
+        let sync2 = true;
+        dir.readdirCB(onReaddir, true);
+        sync2 = false;
+      }
+    };
+    process3();
+    return results;
+  }
+  streamSync(entry = this.cwd, opts = {}) {
+    if (typeof entry === "string") {
+      entry = this.cwd.resolve(entry);
+    } else if (!(entry instanceof PathBase)) {
+      opts = entry;
+      entry = this.cwd;
+    }
+    const { withFileTypes = true, follow = false, filter: filter2, walkFilter } = opts;
+    const results = new Minipass({ objectMode: true });
+    const dirs = /* @__PURE__ */ new Set();
+    if (!filter2 || filter2(entry)) {
+      results.write(withFileTypes ? entry : entry.fullpath());
+    }
+    const queue = [entry];
+    let processing = 0;
+    const process3 = () => {
+      let paused = false;
+      while (!paused) {
+        const dir = queue.shift();
+        if (!dir) {
+          if (processing === 0)
+            results.end();
+          return;
+        }
+        processing++;
+        dirs.add(dir);
+        const entries = dir.readdirSync();
+        for (const e of entries) {
+          if (!filter2 || filter2(e)) {
+            if (!results.write(withFileTypes ? e : e.fullpath())) {
+              paused = true;
+            }
+          }
+        }
+        processing--;
+        for (const e of entries) {
+          let r = e;
+          if (e.isSymbolicLink()) {
+            if (!(follow && (r = e.realpathSync())))
+              continue;
+            if (r.isUnknown())
+              r.lstatSync();
+          }
+          if (r.shouldWalk(dirs, walkFilter)) {
+            queue.push(r);
+          }
+        }
+      }
+      if (paused && !results.flowing)
+        results.once("drain", process3);
+    };
+    process3();
+    return results;
+  }
+  chdir(path4 = this.cwd) {
+    const oldCwd = this.cwd;
+    this.cwd = typeof path4 === "string" ? this.cwd.resolve(path4) : path4;
+    this.cwd[setAsCwd](oldCwd);
+  }
+};
+var PathScurryWin32 = class extends PathScurryBase {
+  /**
+   * separator for generating path strings
+   */
+  sep = "\\";
+  constructor(cwd = process.cwd(), opts = {}) {
+    const { nocase = true } = opts;
+    super(cwd, win32, "\\", { ...opts, nocase });
+    this.nocase = nocase;
+    for (let p = this.cwd; p; p = p.parent) {
+      p.nocase = this.nocase;
+    }
+  }
+  /**
+   * @internal
+   */
+  parseRootPath(dir) {
+    return win32.parse(dir).root.toUpperCase();
+  }
+  /**
+   * @internal
+   */
+  newRoot(fs4) {
+    return new PathWin32(this.rootPath, IFDIR, void 0, this.roots, this.nocase, this.childrenCache(), { fs: fs4 });
+  }
+  /**
+   * Return true if the provided path string is an absolute path
+   */
+  isAbsolute(p) {
+    return p.startsWith("/") || p.startsWith("\\") || /^[a-z]:(\/|\\)/i.test(p);
+  }
+};
+var PathScurryPosix = class extends PathScurryBase {
+  /**
+   * separator for generating path strings
+   */
+  sep = "/";
+  constructor(cwd = process.cwd(), opts = {}) {
+    const { nocase = false } = opts;
+    super(cwd, posix, "/", { ...opts, nocase });
+    this.nocase = nocase;
+  }
+  /**
+   * @internal
+   */
+  parseRootPath(_dir) {
+    return "/";
+  }
+  /**
+   * @internal
+   */
+  newRoot(fs4) {
+    return new PathPosix(this.rootPath, IFDIR, void 0, this.roots, this.nocase, this.childrenCache(), { fs: fs4 });
+  }
+  /**
+   * Return true if the provided path string is an absolute path
+   */
+  isAbsolute(p) {
+    return p.startsWith("/");
+  }
+};
+var PathScurryDarwin = class extends PathScurryPosix {
+  constructor(cwd = process.cwd(), opts = {}) {
+    const { nocase = true } = opts;
+    super(cwd, { ...opts, nocase });
+  }
+};
+var Path = process.platform === "win32" ? PathWin32 : PathPosix;
+var PathScurry = process.platform === "win32" ? PathScurryWin32 : process.platform === "darwin" ? PathScurryDarwin : PathScurryPosix;
+
+// node_modules/glob/dist/esm/glob.js
+import { fileURLToPath as fileURLToPath2 } from "url";
+
+// node_modules/glob/dist/esm/pattern.js
+var isPatternList = (pl) => pl.length >= 1;
+var isGlobList = (gl) => gl.length >= 1;
+var Pattern = class _Pattern {
+  #patternList;
+  #globList;
+  #index;
+  length;
+  #platform;
+  #rest;
+  #globString;
+  #isDrive;
+  #isUNC;
+  #isAbsolute;
+  #followGlobstar = true;
+  constructor(patternList, globList, index, platform) {
+    if (!isPatternList(patternList)) {
+      throw new TypeError("empty pattern list");
+    }
+    if (!isGlobList(globList)) {
+      throw new TypeError("empty glob list");
+    }
+    if (globList.length !== patternList.length) {
+      throw new TypeError("mismatched pattern list and glob list lengths");
+    }
+    this.length = patternList.length;
+    if (index < 0 || index >= this.length) {
+      throw new TypeError("index out of range");
+    }
+    this.#patternList = patternList;
+    this.#globList = globList;
+    this.#index = index;
+    this.#platform = platform;
+    if (this.#index === 0) {
+      if (this.isUNC()) {
+        const [p0, p1, p2, p3, ...prest] = this.#patternList;
+        const [g0, g1, g2, g3, ...grest] = this.#globList;
+        if (prest[0] === "") {
+          prest.shift();
+          grest.shift();
+        }
+        const p = [p0, p1, p2, p3, ""].join("/");
+        const g = [g0, g1, g2, g3, ""].join("/");
+        this.#patternList = [p, ...prest];
+        this.#globList = [g, ...grest];
+        this.length = this.#patternList.length;
+      } else if (this.isDrive() || this.isAbsolute()) {
+        const [p1, ...prest] = this.#patternList;
+        const [g1, ...grest] = this.#globList;
+        if (prest[0] === "") {
+          prest.shift();
+          grest.shift();
+        }
+        const p = p1 + "/";
+        const g = g1 + "/";
+        this.#patternList = [p, ...prest];
+        this.#globList = [g, ...grest];
+        this.length = this.#patternList.length;
+      }
+    }
+  }
+  /**
+   * The first entry in the parsed list of patterns
+   */
+  pattern() {
+    return this.#patternList[this.#index];
+  }
+  /**
+   * true of if pattern() returns a string
+   */
+  isString() {
+    return typeof this.#patternList[this.#index] === "string";
+  }
+  /**
+   * true of if pattern() returns GLOBSTAR
+   */
+  isGlobstar() {
+    return this.#patternList[this.#index] === GLOBSTAR;
+  }
+  /**
+   * true if pattern() returns a regexp
+   */
+  isRegExp() {
+    return this.#patternList[this.#index] instanceof RegExp;
+  }
+  /**
+   * The /-joined set of glob parts that make up this pattern
+   */
+  globString() {
+    return this.#globString = this.#globString || (this.#index === 0 ? this.isAbsolute() ? this.#globList[0] + this.#globList.slice(1).join("/") : this.#globList.join("/") : this.#globList.slice(this.#index).join("/"));
+  }
+  /**
+   * true if there are more pattern parts after this one
+   */
+  hasMore() {
+    return this.length > this.#index + 1;
+  }
+  /**
+   * The rest of the pattern after this part, or null if this is the end
+   */
+  rest() {
+    if (this.#rest !== void 0)
+      return this.#rest;
+    if (!this.hasMore())
+      return this.#rest = null;
+    this.#rest = new _Pattern(this.#patternList, this.#globList, this.#index + 1, this.#platform);
+    this.#rest.#isAbsolute = this.#isAbsolute;
+    this.#rest.#isUNC = this.#isUNC;
+    this.#rest.#isDrive = this.#isDrive;
+    return this.#rest;
+  }
+  /**
+   * true if the pattern represents a //unc/path/ on windows
+   */
+  isUNC() {
+    const pl = this.#patternList;
+    return this.#isUNC !== void 0 ? this.#isUNC : this.#isUNC = this.#platform === "win32" && this.#index === 0 && pl[0] === "" && pl[1] === "" && typeof pl[2] === "string" && !!pl[2] && typeof pl[3] === "string" && !!pl[3];
+  }
+  // pattern like C:/...
+  // split = ['C:', ...]
+  // XXX: would be nice to handle patterns like `c:*` to test the cwd
+  // in c: for *, but I don't know of a way to even figure out what that
+  // cwd is without actually chdir'ing into it?
+  /**
+   * True if the pattern starts with a drive letter on Windows
+   */
+  isDrive() {
+    const pl = this.#patternList;
+    return this.#isDrive !== void 0 ? this.#isDrive : this.#isDrive = this.#platform === "win32" && this.#index === 0 && this.length > 1 && typeof pl[0] === "string" && /^[a-z]:$/i.test(pl[0]);
+  }
+  // pattern = '/' or '/...' or '/x/...'
+  // split = ['', ''] or ['', ...] or ['', 'x', ...]
+  // Drive and UNC both considered absolute on windows
+  /**
+   * True if the pattern is rooted on an absolute path
+   */
+  isAbsolute() {
+    const pl = this.#patternList;
+    return this.#isAbsolute !== void 0 ? this.#isAbsolute : this.#isAbsolute = pl[0] === "" && pl.length > 1 || this.isDrive() || this.isUNC();
+  }
+  /**
+   * consume the root of the pattern, and return it
+   */
+  root() {
+    const p = this.#patternList[0];
+    return typeof p === "string" && this.isAbsolute() && this.#index === 0 ? p : "";
+  }
+  /**
+   * Check to see if the current globstar pattern is allowed to follow
+   * a symbolic link.
+   */
+  checkFollowGlobstar() {
+    return !(this.#index === 0 || !this.isGlobstar() || !this.#followGlobstar);
+  }
+  /**
+   * Mark that the current globstar pattern is following a symbolic link
+   */
+  markFollowGlobstar() {
+    if (this.#index === 0 || !this.isGlobstar() || !this.#followGlobstar)
+      return false;
+    this.#followGlobstar = false;
+    return true;
+  }
+};
+
+// node_modules/glob/dist/esm/ignore.js
+var defaultPlatform2 = typeof process === "object" && process && typeof process.platform === "string" ? process.platform : "linux";
+var Ignore = class {
+  relative;
+  relativeChildren;
+  absolute;
+  absoluteChildren;
+  constructor(ignored, { nobrace, nocase, noext, noglobstar, platform = defaultPlatform2 }) {
+    this.relative = [];
+    this.absolute = [];
+    this.relativeChildren = [];
+    this.absoluteChildren = [];
+    const mmopts = {
+      dot: true,
+      nobrace,
+      nocase,
+      noext,
+      noglobstar,
+      optimizationLevel: 2,
+      platform,
+      nocomment: true,
+      nonegate: true
+    };
+    for (const ign of ignored) {
+      const mm = new Minimatch(ign, mmopts);
+      for (let i = 0; i < mm.set.length; i++) {
+        const parsed = mm.set[i];
+        const globParts = mm.globParts[i];
+        if (!parsed || !globParts) {
+          throw new Error("invalid pattern object");
+        }
+        while (parsed[0] === "." && globParts[0] === ".") {
+          parsed.shift();
+          globParts.shift();
+        }
+        const p = new Pattern(parsed, globParts, 0, platform);
+        const m = new Minimatch(p.globString(), mmopts);
+        const children = globParts[globParts.length - 1] === "**";
+        const absolute = p.isAbsolute();
+        if (absolute)
+          this.absolute.push(m);
+        else
+          this.relative.push(m);
+        if (children) {
+          if (absolute)
+            this.absoluteChildren.push(m);
+          else
+            this.relativeChildren.push(m);
+        }
+      }
+    }
+  }
+  ignored(p) {
+    const fullpath = p.fullpath();
+    const fullpaths = `${fullpath}/`;
+    const relative = p.relative() || ".";
+    const relatives = `${relative}/`;
+    for (const m of this.relative) {
+      if (m.match(relative) || m.match(relatives))
+        return true;
+    }
+    for (const m of this.absolute) {
+      if (m.match(fullpath) || m.match(fullpaths))
+        return true;
+    }
+    return false;
+  }
+  childrenIgnored(p) {
+    const fullpath = p.fullpath() + "/";
+    const relative = (p.relative() || ".") + "/";
+    for (const m of this.relativeChildren) {
+      if (m.match(relative))
+        return true;
+    }
+    for (const m of this.absoluteChildren) {
+      if (m.match(fullpath))
+        return true;
+    }
+    return false;
+  }
+};
+
+// node_modules/glob/dist/esm/processor.js
+var HasWalkedCache = class _HasWalkedCache {
+  store;
+  constructor(store = /* @__PURE__ */ new Map()) {
+    this.store = store;
+  }
+  copy() {
+    return new _HasWalkedCache(new Map(this.store));
+  }
+  hasWalked(target, pattern) {
+    return this.store.get(target.fullpath())?.has(pattern.globString());
+  }
+  storeWalked(target, pattern) {
+    const fullpath = target.fullpath();
+    const cached = this.store.get(fullpath);
+    if (cached)
+      cached.add(pattern.globString());
+    else
+      this.store.set(fullpath, /* @__PURE__ */ new Set([pattern.globString()]));
+  }
+};
+var MatchRecord = class {
+  store = /* @__PURE__ */ new Map();
+  add(target, absolute, ifDir) {
+    const n = (absolute ? 2 : 0) | (ifDir ? 1 : 0);
+    const current = this.store.get(target);
+    this.store.set(target, current === void 0 ? n : n & current);
+  }
+  // match, absolute, ifdir
+  entries() {
+    return [...this.store.entries()].map(([path4, n]) => [
+      path4,
+      !!(n & 2),
+      !!(n & 1)
+    ]);
+  }
+};
+var SubWalks = class {
+  store = /* @__PURE__ */ new Map();
+  add(target, pattern) {
+    if (!target.canReaddir()) {
+      return;
+    }
+    const subs = this.store.get(target);
+    if (subs) {
+      if (!subs.find((p) => p.globString() === pattern.globString())) {
+        subs.push(pattern);
+      }
+    } else
+      this.store.set(target, [pattern]);
+  }
+  get(target) {
+    const subs = this.store.get(target);
+    if (!subs) {
+      throw new Error("attempting to walk unknown path");
+    }
+    return subs;
+  }
+  entries() {
+    return this.keys().map((k) => [k, this.store.get(k)]);
+  }
+  keys() {
+    return [...this.store.keys()].filter((t) => t.canReaddir());
+  }
+};
+var Processor = class _Processor {
+  hasWalkedCache;
+  matches = new MatchRecord();
+  subwalks = new SubWalks();
+  patterns;
+  follow;
+  dot;
+  opts;
+  constructor(opts, hasWalkedCache) {
+    this.opts = opts;
+    this.follow = !!opts.follow;
+    this.dot = !!opts.dot;
+    this.hasWalkedCache = hasWalkedCache ? hasWalkedCache.copy() : new HasWalkedCache();
+  }
+  processPatterns(target, patterns) {
+    this.patterns = patterns;
+    const processingSet = patterns.map((p) => [target, p]);
+    for (let [t, pattern] of processingSet) {
+      this.hasWalkedCache.storeWalked(t, pattern);
+      const root = pattern.root();
+      const absolute = pattern.isAbsolute() && this.opts.absolute !== false;
+      if (root) {
+        t = t.resolve(root === "/" && this.opts.root !== void 0 ? this.opts.root : root);
+        const rest2 = pattern.rest();
+        if (!rest2) {
+          this.matches.add(t, true, false);
+          continue;
+        } else {
+          pattern = rest2;
+        }
+      }
+      if (t.isENOENT())
+        continue;
+      let p;
+      let rest;
+      let changed = false;
+      while (typeof (p = pattern.pattern()) === "string" && (rest = pattern.rest())) {
+        const c = t.resolve(p);
+        t = c;
+        pattern = rest;
+        changed = true;
+      }
+      p = pattern.pattern();
+      rest = pattern.rest();
+      if (changed) {
+        if (this.hasWalkedCache.hasWalked(t, pattern))
+          continue;
+        this.hasWalkedCache.storeWalked(t, pattern);
+      }
+      if (typeof p === "string") {
+        const ifDir = p === ".." || p === "" || p === ".";
+        this.matches.add(t.resolve(p), absolute, ifDir);
+        continue;
+      } else if (p === GLOBSTAR) {
+        if (!t.isSymbolicLink() || this.follow || pattern.checkFollowGlobstar()) {
+          this.subwalks.add(t, pattern);
+        }
+        const rp = rest?.pattern();
+        const rrest = rest?.rest();
+        if (!rest || (rp === "" || rp === ".") && !rrest) {
+          this.matches.add(t, absolute, rp === "" || rp === ".");
+        } else {
+          if (rp === "..") {
+            const tp = t.parent || t;
+            if (!rrest)
+              this.matches.add(tp, absolute, true);
+            else if (!this.hasWalkedCache.hasWalked(tp, rrest)) {
+              this.subwalks.add(tp, rrest);
+            }
+          }
+        }
+      } else if (p instanceof RegExp) {
+        this.subwalks.add(t, pattern);
+      }
+    }
+    return this;
+  }
+  subwalkTargets() {
+    return this.subwalks.keys();
+  }
+  child() {
+    return new _Processor(this.opts, this.hasWalkedCache);
+  }
+  // return a new Processor containing the subwalks for each
+  // child entry, and a set of matches, and
+  // a hasWalkedCache that's a copy of this one
+  // then we're going to call
+  filterEntries(parent, entries) {
+    const patterns = this.subwalks.get(parent);
+    const results = this.child();
+    for (const e of entries) {
+      for (const pattern of patterns) {
+        const absolute = pattern.isAbsolute();
+        const p = pattern.pattern();
+        const rest = pattern.rest();
+        if (p === GLOBSTAR) {
+          results.testGlobstar(e, pattern, rest, absolute);
+        } else if (p instanceof RegExp) {
+          results.testRegExp(e, p, rest, absolute);
+        } else {
+          results.testString(e, p, rest, absolute);
+        }
+      }
+    }
+    return results;
+  }
+  testGlobstar(e, pattern, rest, absolute) {
+    if (this.dot || !e.name.startsWith(".")) {
+      if (!pattern.hasMore()) {
+        this.matches.add(e, absolute, false);
+      }
+      if (e.canReaddir()) {
+        if (this.follow || !e.isSymbolicLink()) {
+          this.subwalks.add(e, pattern);
+        } else if (e.isSymbolicLink()) {
+          if (rest && pattern.checkFollowGlobstar()) {
+            this.subwalks.add(e, rest);
+          } else if (pattern.markFollowGlobstar()) {
+            this.subwalks.add(e, pattern);
+          }
+        }
+      }
+    }
+    if (rest) {
+      const rp = rest.pattern();
+      if (typeof rp === "string" && // dots and empty were handled already
+      rp !== ".." && rp !== "" && rp !== ".") {
+        this.testString(e, rp, rest.rest(), absolute);
+      } else if (rp === "..") {
+        const ep = e.parent || e;
+        this.subwalks.add(ep, rest);
+      } else if (rp instanceof RegExp) {
+        this.testRegExp(e, rp, rest.rest(), absolute);
+      }
+    }
+  }
+  testRegExp(e, p, rest, absolute) {
+    if (!p.test(e.name))
+      return;
+    if (!rest) {
+      this.matches.add(e, absolute, false);
+    } else {
+      this.subwalks.add(e, rest);
+    }
+  }
+  testString(e, p, rest, absolute) {
+    if (!e.isNamed(p))
+      return;
+    if (!rest) {
+      this.matches.add(e, absolute, false);
+    } else {
+      this.subwalks.add(e, rest);
+    }
+  }
+};
+
+// node_modules/glob/dist/esm/walker.js
+var makeIgnore = (ignore, opts) => typeof ignore === "string" ? new Ignore([ignore], opts) : Array.isArray(ignore) ? new Ignore(ignore, opts) : ignore;
+var GlobUtil = class {
+  path;
+  patterns;
+  opts;
+  seen = /* @__PURE__ */ new Set();
+  paused = false;
+  aborted = false;
+  #onResume = [];
+  #ignore;
+  #sep;
+  signal;
+  maxDepth;
+  constructor(patterns, path4, opts) {
+    this.patterns = patterns;
+    this.path = path4;
+    this.opts = opts;
+    this.#sep = !opts.posix && opts.platform === "win32" ? "\\" : "/";
+    if (opts.ignore) {
+      this.#ignore = makeIgnore(opts.ignore, opts);
+    }
+    this.maxDepth = opts.maxDepth || Infinity;
+    if (opts.signal) {
+      this.signal = opts.signal;
+      this.signal.addEventListener("abort", () => {
+        this.#onResume.length = 0;
+      });
+    }
+  }
+  #ignored(path4) {
+    return this.seen.has(path4) || !!this.#ignore?.ignored?.(path4);
+  }
+  #childrenIgnored(path4) {
+    return !!this.#ignore?.childrenIgnored?.(path4);
+  }
+  // backpressure mechanism
+  pause() {
+    this.paused = true;
+  }
+  resume() {
+    if (this.signal?.aborted)
+      return;
+    this.paused = false;
+    let fn = void 0;
+    while (!this.paused && (fn = this.#onResume.shift())) {
+      fn();
+    }
+  }
+  onResume(fn) {
+    if (this.signal?.aborted)
+      return;
+    if (!this.paused) {
+      fn();
+    } else {
+      this.#onResume.push(fn);
+    }
+  }
+  // do the requisite realpath/stat checking, and return the path
+  // to add or undefined to filter it out.
+  async matchCheck(e, ifDir) {
+    if (ifDir && this.opts.nodir)
+      return void 0;
+    let rpc;
+    if (this.opts.realpath) {
+      rpc = e.realpathCached() || await e.realpath();
+      if (!rpc)
+        return void 0;
+      e = rpc;
+    }
+    const needStat = e.isUnknown() || this.opts.stat;
+    const s = needStat ? await e.lstat() : e;
+    if (this.opts.follow && this.opts.nodir && s?.isSymbolicLink()) {
+      const target = await s.realpath();
+      if (target && (target.isUnknown() || this.opts.stat)) {
+        await target.lstat();
+      }
+    }
+    return this.matchCheckTest(s, ifDir);
+  }
+  matchCheckTest(e, ifDir) {
+    return e && (this.maxDepth === Infinity || e.depth() <= this.maxDepth) && (!ifDir || e.canReaddir()) && (!this.opts.nodir || !e.isDirectory()) && (!this.opts.nodir || !this.opts.follow || !e.isSymbolicLink() || !e.realpathCached()?.isDirectory()) && !this.#ignored(e) ? e : void 0;
+  }
+  matchCheckSync(e, ifDir) {
+    if (ifDir && this.opts.nodir)
+      return void 0;
+    let rpc;
+    if (this.opts.realpath) {
+      rpc = e.realpathCached() || e.realpathSync();
+      if (!rpc)
+        return void 0;
+      e = rpc;
+    }
+    const needStat = e.isUnknown() || this.opts.stat;
+    const s = needStat ? e.lstatSync() : e;
+    if (this.opts.follow && this.opts.nodir && s?.isSymbolicLink()) {
+      const target = s.realpathSync();
+      if (target && (target?.isUnknown() || this.opts.stat)) {
+        target.lstatSync();
+      }
+    }
+    return this.matchCheckTest(s, ifDir);
+  }
+  matchFinish(e, absolute) {
+    if (this.#ignored(e))
+      return;
+    const abs = this.opts.absolute === void 0 ? absolute : this.opts.absolute;
+    this.seen.add(e);
+    const mark = this.opts.mark && e.isDirectory() ? this.#sep : "";
+    if (this.opts.withFileTypes) {
+      this.matchEmit(e);
+    } else if (abs) {
+      const abs2 = this.opts.posix ? e.fullpathPosix() : e.fullpath();
+      this.matchEmit(abs2 + mark);
+    } else {
+      const rel = this.opts.posix ? e.relativePosix() : e.relative();
+      const pre = this.opts.dotRelative && !rel.startsWith(".." + this.#sep) ? "." + this.#sep : "";
+      this.matchEmit(!rel ? "." + mark : pre + rel + mark);
+    }
+  }
+  async match(e, absolute, ifDir) {
+    const p = await this.matchCheck(e, ifDir);
+    if (p)
+      this.matchFinish(p, absolute);
+  }
+  matchSync(e, absolute, ifDir) {
+    const p = this.matchCheckSync(e, ifDir);
+    if (p)
+      this.matchFinish(p, absolute);
+  }
+  walkCB(target, patterns, cb) {
+    if (this.signal?.aborted)
+      cb();
+    this.walkCB2(target, patterns, new Processor(this.opts), cb);
+  }
+  walkCB2(target, patterns, processor, cb) {
+    if (this.#childrenIgnored(target))
+      return cb();
+    if (this.signal?.aborted)
+      cb();
+    if (this.paused) {
+      this.onResume(() => this.walkCB2(target, patterns, processor, cb));
+      return;
+    }
+    processor.processPatterns(target, patterns);
+    let tasks = 1;
+    const next = () => {
+      if (--tasks === 0)
+        cb();
+    };
+    for (const [m, absolute, ifDir] of processor.matches.entries()) {
+      if (this.#ignored(m))
+        continue;
+      tasks++;
+      this.match(m, absolute, ifDir).then(() => next());
+    }
+    for (const t of processor.subwalkTargets()) {
+      if (this.maxDepth !== Infinity && t.depth() >= this.maxDepth) {
+        continue;
+      }
+      tasks++;
+      const childrenCached = t.readdirCached();
+      if (t.calledReaddir())
+        this.walkCB3(t, childrenCached, processor, next);
+      else {
+        t.readdirCB((_, entries) => this.walkCB3(t, entries, processor, next), true);
+      }
+    }
+    next();
+  }
+  walkCB3(target, entries, processor, cb) {
+    processor = processor.filterEntries(target, entries);
+    let tasks = 1;
+    const next = () => {
+      if (--tasks === 0)
+        cb();
+    };
+    for (const [m, absolute, ifDir] of processor.matches.entries()) {
+      if (this.#ignored(m))
+        continue;
+      tasks++;
+      this.match(m, absolute, ifDir).then(() => next());
+    }
+    for (const [target2, patterns] of processor.subwalks.entries()) {
+      tasks++;
+      this.walkCB2(target2, patterns, processor.child(), next);
+    }
+    next();
+  }
+  walkCBSync(target, patterns, cb) {
+    if (this.signal?.aborted)
+      cb();
+    this.walkCB2Sync(target, patterns, new Processor(this.opts), cb);
+  }
+  walkCB2Sync(target, patterns, processor, cb) {
+    if (this.#childrenIgnored(target))
+      return cb();
+    if (this.signal?.aborted)
+      cb();
+    if (this.paused) {
+      this.onResume(() => this.walkCB2Sync(target, patterns, processor, cb));
+      return;
+    }
+    processor.processPatterns(target, patterns);
+    let tasks = 1;
+    const next = () => {
+      if (--tasks === 0)
+        cb();
+    };
+    for (const [m, absolute, ifDir] of processor.matches.entries()) {
+      if (this.#ignored(m))
+        continue;
+      this.matchSync(m, absolute, ifDir);
+    }
+    for (const t of processor.subwalkTargets()) {
+      if (this.maxDepth !== Infinity && t.depth() >= this.maxDepth) {
+        continue;
+      }
+      tasks++;
+      const children = t.readdirSync();
+      this.walkCB3Sync(t, children, processor, next);
+    }
+    next();
+  }
+  walkCB3Sync(target, entries, processor, cb) {
+    processor = processor.filterEntries(target, entries);
+    let tasks = 1;
+    const next = () => {
+      if (--tasks === 0)
+        cb();
+    };
+    for (const [m, absolute, ifDir] of processor.matches.entries()) {
+      if (this.#ignored(m))
+        continue;
+      this.matchSync(m, absolute, ifDir);
+    }
+    for (const [target2, patterns] of processor.subwalks.entries()) {
+      tasks++;
+      this.walkCB2Sync(target2, patterns, processor.child(), next);
+    }
+    next();
+  }
+};
+var GlobWalker = class extends GlobUtil {
+  matches;
+  constructor(patterns, path4, opts) {
+    super(patterns, path4, opts);
+    this.matches = /* @__PURE__ */ new Set();
+  }
+  matchEmit(e) {
+    this.matches.add(e);
+  }
+  async walk() {
+    if (this.signal?.aborted)
+      throw this.signal.reason;
+    if (this.path.isUnknown()) {
+      await this.path.lstat();
+    }
+    await new Promise((res, rej) => {
+      this.walkCB(this.path, this.patterns, () => {
+        if (this.signal?.aborted) {
+          rej(this.signal.reason);
+        } else {
+          res(this.matches);
+        }
+      });
+    });
+    return this.matches;
+  }
+  walkSync() {
+    if (this.signal?.aborted)
+      throw this.signal.reason;
+    if (this.path.isUnknown()) {
+      this.path.lstatSync();
+    }
+    this.walkCBSync(this.path, this.patterns, () => {
+      if (this.signal?.aborted)
+        throw this.signal.reason;
+    });
+    return this.matches;
+  }
+};
+var GlobStream = class extends GlobUtil {
+  results;
+  constructor(patterns, path4, opts) {
+    super(patterns, path4, opts);
+    this.results = new Minipass({
+      signal: this.signal,
+      objectMode: true
+    });
+    this.results.on("drain", () => this.resume());
+    this.results.on("resume", () => this.resume());
+  }
+  matchEmit(e) {
+    this.results.write(e);
+    if (!this.results.flowing)
+      this.pause();
+  }
+  stream() {
+    const target = this.path;
+    if (target.isUnknown()) {
+      target.lstat().then(() => {
+        this.walkCB(target, this.patterns, () => this.results.end());
+      });
+    } else {
+      this.walkCB(target, this.patterns, () => this.results.end());
+    }
+    return this.results;
+  }
+  streamSync() {
+    if (this.path.isUnknown()) {
+      this.path.lstatSync();
+    }
+    this.walkCBSync(this.path, this.patterns, () => this.results.end());
+    return this.results;
+  }
+};
+
+// node_modules/glob/dist/esm/glob.js
+var defaultPlatform3 = typeof process === "object" && process && typeof process.platform === "string" ? process.platform : "linux";
+var Glob = class {
+  absolute;
+  cwd;
+  root;
+  dot;
+  dotRelative;
+  follow;
+  ignore;
+  magicalBraces;
+  mark;
+  matchBase;
+  maxDepth;
+  nobrace;
+  nocase;
+  nodir;
+  noext;
+  noglobstar;
+  pattern;
+  platform;
+  realpath;
+  scurry;
+  stat;
+  signal;
+  windowsPathsNoEscape;
+  withFileTypes;
+  /**
+   * The options provided to the constructor.
+   */
+  opts;
+  /**
+   * An array of parsed immutable {@link Pattern} objects.
+   */
+  patterns;
+  /**
+   * All options are stored as properties on the `Glob` object.
+   *
+   * See {@link GlobOptions} for full options descriptions.
+   *
+   * Note that a previous `Glob` object can be passed as the
+   * `GlobOptions` to another `Glob` instantiation to re-use settings
+   * and caches with a new pattern.
+   *
+   * Traversal functions can be called multiple times to run the walk
+   * again.
+   */
+  constructor(pattern, opts) {
+    if (!opts)
+      throw new TypeError("glob options required");
+    this.withFileTypes = !!opts.withFileTypes;
+    this.signal = opts.signal;
+    this.follow = !!opts.follow;
+    this.dot = !!opts.dot;
+    this.dotRelative = !!opts.dotRelative;
+    this.nodir = !!opts.nodir;
+    this.mark = !!opts.mark;
+    if (!opts.cwd) {
+      this.cwd = "";
+    } else if (opts.cwd instanceof URL || opts.cwd.startsWith("file://")) {
+      opts.cwd = fileURLToPath2(opts.cwd);
+    }
+    this.cwd = opts.cwd || "";
+    this.root = opts.root;
+    this.magicalBraces = !!opts.magicalBraces;
+    this.nobrace = !!opts.nobrace;
+    this.noext = !!opts.noext;
+    this.realpath = !!opts.realpath;
+    this.absolute = opts.absolute;
+    this.noglobstar = !!opts.noglobstar;
+    this.matchBase = !!opts.matchBase;
+    this.maxDepth = typeof opts.maxDepth === "number" ? opts.maxDepth : Infinity;
+    this.stat = !!opts.stat;
+    this.ignore = opts.ignore;
+    if (this.withFileTypes && this.absolute !== void 0) {
+      throw new Error("cannot set absolute and withFileTypes:true");
+    }
+    if (typeof pattern === "string") {
+      pattern = [pattern];
+    }
+    this.windowsPathsNoEscape = !!opts.windowsPathsNoEscape || opts.allowWindowsEscape === false;
+    if (this.windowsPathsNoEscape) {
+      pattern = pattern.map((p) => p.replace(/\\/g, "/"));
+    }
+    if (this.matchBase) {
+      if (opts.noglobstar) {
+        throw new TypeError("base matching requires globstar");
+      }
+      pattern = pattern.map((p) => p.includes("/") ? p : `./**/${p}`);
+    }
+    this.pattern = pattern;
+    this.platform = opts.platform || defaultPlatform3;
+    this.opts = { ...opts, platform: this.platform };
+    if (opts.scurry) {
+      this.scurry = opts.scurry;
+      if (opts.nocase !== void 0 && opts.nocase !== opts.scurry.nocase) {
+        throw new Error("nocase option contradicts provided scurry option");
+      }
+    } else {
+      const Scurry = opts.platform === "win32" ? PathScurryWin32 : opts.platform === "darwin" ? PathScurryDarwin : opts.platform ? PathScurryPosix : PathScurry;
+      this.scurry = new Scurry(this.cwd, {
+        nocase: opts.nocase,
+        fs: opts.fs
+      });
+    }
+    this.nocase = this.scurry.nocase;
+    const nocaseMagicOnly = this.platform === "darwin" || this.platform === "win32";
+    const mmo = {
+      // default nocase based on platform
+      ...opts,
+      dot: this.dot,
+      matchBase: this.matchBase,
+      nobrace: this.nobrace,
+      nocase: this.nocase,
+      nocaseMagicOnly,
+      nocomment: true,
+      noext: this.noext,
+      nonegate: true,
+      optimizationLevel: 2,
+      platform: this.platform,
+      windowsPathsNoEscape: this.windowsPathsNoEscape,
+      debug: !!this.opts.debug
+    };
+    const mms = this.pattern.map((p) => new Minimatch(p, mmo));
+    const [matchSet, globParts] = mms.reduce((set, m) => {
+      set[0].push(...m.set);
+      set[1].push(...m.globParts);
+      return set;
+    }, [[], []]);
+    this.patterns = matchSet.map((set, i) => {
+      const g = globParts[i];
+      if (!g)
+        throw new Error("invalid pattern object");
+      return new Pattern(set, g, 0, this.platform);
+    });
+  }
+  async walk() {
+    return [
+      ...await new GlobWalker(this.patterns, this.scurry.cwd, {
+        ...this.opts,
+        maxDepth: this.maxDepth !== Infinity ? this.maxDepth + this.scurry.cwd.depth() : Infinity,
+        platform: this.platform,
+        nocase: this.nocase
+      }).walk()
+    ];
+  }
+  walkSync() {
+    return [
+      ...new GlobWalker(this.patterns, this.scurry.cwd, {
+        ...this.opts,
+        maxDepth: this.maxDepth !== Infinity ? this.maxDepth + this.scurry.cwd.depth() : Infinity,
+        platform: this.platform,
+        nocase: this.nocase
+      }).walkSync()
+    ];
+  }
+  stream() {
+    return new GlobStream(this.patterns, this.scurry.cwd, {
+      ...this.opts,
+      maxDepth: this.maxDepth !== Infinity ? this.maxDepth + this.scurry.cwd.depth() : Infinity,
+      platform: this.platform,
+      nocase: this.nocase
+    }).stream();
+  }
+  streamSync() {
+    return new GlobStream(this.patterns, this.scurry.cwd, {
+      ...this.opts,
+      maxDepth: this.maxDepth !== Infinity ? this.maxDepth + this.scurry.cwd.depth() : Infinity,
+      platform: this.platform,
+      nocase: this.nocase
+    }).streamSync();
+  }
+  /**
+   * Default sync iteration function. Returns a Generator that
+   * iterates over the results.
+   */
+  iterateSync() {
+    return this.streamSync()[Symbol.iterator]();
+  }
+  [Symbol.iterator]() {
+    return this.iterateSync();
+  }
+  /**
+   * Default async iteration function. Returns an AsyncGenerator that
+   * iterates over the results.
+   */
+  iterate() {
+    return this.stream()[Symbol.asyncIterator]();
+  }
+  [Symbol.asyncIterator]() {
+    return this.iterate();
+  }
+};
+
+// node_modules/glob/dist/esm/has-magic.js
+var hasMagic = (pattern, options = {}) => {
+  if (!Array.isArray(pattern)) {
+    pattern = [pattern];
+  }
+  for (const p of pattern) {
+    if (new Minimatch(p, options).hasMagic())
+      return true;
+  }
+  return false;
+};
+
+// node_modules/glob/dist/esm/index.js
+function globStreamSync(pattern, options = {}) {
+  return new Glob(pattern, options).streamSync();
+}
+function globStream(pattern, options = {}) {
+  return new Glob(pattern, options).stream();
+}
+function globSync(pattern, options = {}) {
+  return new Glob(pattern, options).walkSync();
+}
+async function glob_(pattern, options = {}) {
+  return new Glob(pattern, options).walk();
+}
+function globIterateSync(pattern, options = {}) {
+  return new Glob(pattern, options).iterateSync();
+}
+function globIterate(pattern, options = {}) {
+  return new Glob(pattern, options).iterate();
+}
+var streamSync = globStreamSync;
+var stream = Object.assign(globStream, { sync: globStreamSync });
+var iterateSync = globIterateSync;
+var iterate = Object.assign(globIterate, {
+  sync: globIterateSync
+});
+var sync = Object.assign(globSync, {
+  stream: globStreamSync,
+  iterate: globIterateSync
+});
+var glob = Object.assign(glob_, {
+  glob: glob_,
+  globSync,
+  sync,
+  globStream,
+  stream,
+  globStreamSync,
+  streamSync,
+  globIterate,
+  iterate,
+  globIterateSync,
+  iterateSync,
+  Glob,
+  hasMagic,
+  escape,
+  unescape
+});
+glob.glob = glob;
 
 // src/utils.ts
 import fs from "node:fs";
-function loadJsonFile(path3) {
-  return JSON.parse(fs.readFileSync(path3).toString("utf-8"));
+function loadJsonFile(path4) {
+  return JSON.parse(fs.readFileSync(path4).toString("utf-8"));
 }
-function loadMetaFile(path3) {
-  return loadJsonFile(path3);
+function loadMetaFile(path4) {
+  return loadJsonFile(path4);
 }
-function loadAnalysisJson(path3) {
-  return loadJsonFile(path3);
+function loadAnalysisJson(path4) {
+  return loadJsonFile(path4);
 }
 function getSingleInput(name) {
   const val = process.env[`INPUT_${name.toUpperCase()}`] || "";
   return val.trim();
 }
 
+// src/report.ts
+function report(input) {
+  const allPageSizes = getAllPageSizes(input);
+  fs2.mkdirSync(path2.join(process2.cwd(), input.analyzerDirectory), {
+    recursive: true
+  });
+  const resultJsonPath = path2.join(
+    process2.cwd(),
+    input.analyzerDirectory,
+    "bundle_analysis.json"
+  );
+  fs2.writeFileSync(resultJsonPath, JSON.stringify(allPageSizes, null, 2));
+  console2.log(`Wrote ${resultJsonPath}`);
+}
+function findMetafiles(input) {
+  return input.metafiles.flatMap((metafile) => {
+    return globSync(path2.join(process2.cwd(), metafile), {
+      nodir: true
+    }).map((metaFilePath) => {
+      return {
+        relativePath: path2.relative(process2.cwd(), metaFilePath),
+        absolutePath: metaFilePath
+      };
+    });
+  });
+}
+function getAllPageSizes(input) {
+  const acc = {};
+  return findMetafiles(input).reduce((acc2, { relativePath, absolutePath }) => {
+    try {
+      fs2.accessSync(absolutePath, fs2.constants.R_OK);
+    } catch (err) {
+      console2.error(
+        `No meta file found at "${absolutePath}" - a path to meta file may be wrong, or esbuild is not executed.`
+      );
+      process2.exit(1);
+    }
+    const metaFileJson = loadMetaFile(absolutePath);
+    Object.entries(metaFileJson.outputs).reduce((acc3, output) => {
+      const [outfile, buildMeta] = output;
+      if (!input.includeExtensions.some(
+        (ext2) => outfile.toLowerCase().endsWith(ext2)
+      )) {
+        return acc3;
+      }
+      acc3[`${relativePath} -> ${outfile}`] = {
+        bytes: buildMeta.bytes,
+        metafile: relativePath,
+        outfile
+      };
+      return acc3;
+    }, acc2);
+    return acc2;
+  }, acc);
+}
+
 // src/compare.ts
 function compare(input) {
   let hasAnyChange = false;
@@ -29,7 +6569,7 @@ function compare(input) {
 This analysis was generated by [esbuild-bundle-analyzer](https://github.com/exoego/esbuild-bundle-analyzer). \u{1F916}
 `;
   const current = loadAnalysisJson(
-    path.join(process.cwd(), input.analyzerDirectory, "bundle_analysis.json")
+    path3.join(process.cwd(), input.analyzerDirectory, "bundle_analysis.json")
   );
   const base = loadBaseAnalysisJson(input);
   const fileTree = buildFileTree(input);
@@ -75,11 +6615,11 @@ function treeKey(metafile, outfile) {
   return `${metafile} -> ${outfile}`;
 }
 function writeComment(input, output) {
-  fs2.mkdirSync(path.join(process.cwd(), input.analyzerDirectory), {
+  fs3.mkdirSync(path3.join(process.cwd(), input.analyzerDirectory), {
     recursive: true
   });
-  fs2.writeFileSync(
-    path.join(
+  fs3.writeFileSync(
+    path3.join(
       process.cwd(),
       input.analyzerDirectory,
       "bundle_analysis_comment.txt"
@@ -108,7 +6648,7 @@ function detail(input) {
 function loadBaseAnalysisJson(input) {
   try {
     return loadAnalysisJson(
-      path.join(
+      path3.join(
         process.cwd(),
         input.analyzerDirectory,
         "base/bundle/bundle_analysis.json"
@@ -150,13 +6690,13 @@ function buildFileTree(input) {
   if (input.topNLargestPaths <= 0) {
     return trees;
   }
-  for (const metafile of input.metafiles) {
-    const metafileJson = loadMetaFile(path.join(process.cwd(), metafile));
+  for (const { relativePath, absolutePath } of findMetafiles(input)) {
+    const metafileJson = loadMetaFile(absolutePath);
     for (const [outfile, buildMeta] of Object.entries(metafileJson.outputs)) {
       const tree = buildRoot(buildMeta.inputs);
-      trees.set(treeKey(metafile, outfile), tree);
-      fs2.writeFileSync(
-        path.join(process.cwd(), input.analyzerDirectory, "tree.json"),
+      trees.set(treeKey(relativePath, outfile), tree);
+      fs3.writeFileSync(
+        path3.join(process.cwd(), input.analyzerDirectory, "tree.json"),
         JSON.stringify(tree, null, 2)
       );
     }
@@ -250,9 +6790,9 @@ function fileSizeTable(data, topNLargestPaths) {
       d.tree,
       topNLargestPaths
     );
-    for (const { path: path3, value } of largeNodes) {
+    for (const { path: path4, value } of largeNodes) {
       const percent = fixedPercent(value, totalSize);
-      output += `| ${path3} | ${renderBar(percent, value)} |
+      output += `| ${path4} | ${renderBar(percent, value)} |
 `;
     }
     if (hasOther) {
@@ -315,54 +6855,6 @@ function renderStatusIndicator(percentChange, redThreshold) {
   return `${res} ${sign(percentChange)}`;
 }
 
-// src/report.ts
-import fs3 from "node:fs";
-import path2 from "node:path";
-import process2 from "node:process";
-function report(input) {
-  const allPageSizes = getAllPageSizes(input);
-  fs3.mkdirSync(path2.join(process2.cwd(), input.analyzerDirectory), {
-    recursive: true
-  });
-  const resultJsonPath = path2.join(
-    process2.cwd(),
-    input.analyzerDirectory,
-    "bundle_analysis.json"
-  );
-  fs3.writeFileSync(resultJsonPath, JSON.stringify(allPageSizes, null, 2));
-  console.log(`Wrote ${resultJsonPath}`);
-}
-function getAllPageSizes(input) {
-  const acc = {};
-  return input.metafiles.reduce((acc2, metafile) => {
-    const metaFilePath = path2.join(process2.cwd(), metafile);
-    try {
-      fs3.accessSync(metaFilePath, fs3.constants.R_OK);
-    } catch (err) {
-      console.error(
-        `No meta file found at "${metaFilePath}" - a path to meta file may be wrong, or esbuild is not executed.`
-      );
-      process2.exit(1);
-    }
-    const metaFileJson = loadMetaFile(metaFilePath);
-    Object.entries(metaFileJson.outputs).reduce((acc3, output) => {
-      const [outfile, buildMeta] = output;
-      if (!input.includeExtensions.some(
-        (ext) => outfile.toLowerCase().endsWith(ext)
-      )) {
-        return acc3;
-      }
-      acc3[`${metafile} -> ${outfile}`] = {
-        bytes: buildMeta.bytes,
-        metafile,
-        outfile
-      };
-      return acc3;
-    }, acc2);
-    return acc2;
-  }, acc);
-}
-
 // src/index.ts
 function getInput() {
   const rawMetafiles = getSingleInput("metafiles");
@@ -401,4 +6893,4 @@ if (import.meta.url === pathToFileURL(process.argv[1]).href) {
 export {
   run
 };
-//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vc3JjL2luZGV4LnRzIiwgIi4uL3NyYy9jb21wYXJlLnRzIiwgIi4uL3NyYy91dGlscy50cyIsICIuLi9zcmMvcmVwb3J0LnRzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWyJpbXBvcnQgeyBwYXRoVG9GaWxlVVJMIH0gZnJvbSBcIm5vZGU6dXJsXCI7XG5pbXBvcnQgeyBjb21wYXJlIH0gZnJvbSBcIi4vY29tcGFyZVwiO1xuaW1wb3J0IHsgcmVwb3J0IH0gZnJvbSBcIi4vcmVwb3J0XCI7XG5pbXBvcnQgdHlwZSB7IElucHV0IH0gZnJvbSBcIi4vdHlwZXNcIjtcbmltcG9ydCB7IGdldFNpbmdsZUlucHV0IH0gZnJvbSBcIi4vdXRpbHNcIjtcblxuZnVuY3Rpb24gZ2V0SW5wdXQoKTogSW5wdXQge1xuXHRjb25zdCByYXdNZXRhZmlsZXMgPSBnZXRTaW5nbGVJbnB1dChcIm1ldGFmaWxlc1wiKTtcblx0aWYgKCFyYXdNZXRhZmlsZXMpIHtcblx0XHR0aHJvdyBuZXcgRXJyb3IoXCJtZXRhZmlsZXMgaXMgbm90IHNwZWNpZmllZFwiKTtcblx0fVxuXHRjb25zdCBuYW1lID0gZ2V0U2luZ2xlSW5wdXQoXCJuYW1lXCIpO1xuXHRpZiAoIW5hbWUpIHtcblx0XHR0aHJvdyBuZXcgRXJyb3IoXCJuYW1lIGlzIG5vdCBzcGVjaWZpZWRcIik7XG5cdH1cblx0cmV0dXJuIHtcblx0XHRwZXJjZW50RXh0cmFBdHRlbnRpb246IE51bWJlci5wYXJzZUludChcblx0XHRcdGdldFNpbmdsZUlucHV0KFwicGVyY2VudF9leHRyYV9hdHRlbnRpb25cIikgfHwgXCIyMFwiLFxuXHRcdFx0MTAsXG5cdFx0KSxcblx0XHRzaG93RGV0YWlsczogW1widHJ1ZVwiLCBcIlRydWVcIiwgXCJUUlVFXCJdLmluY2x1ZGVzKFxuXHRcdFx0Z2V0U2luZ2xlSW5wdXQoXCJzaG93X2RldGFpbHNcIikgfHwgXCJ0cnVlXCIsXG5cdFx0KSxcblx0XHR0b3BOTGFyZ2VzdFBhdGhzOiBOdW1iZXIucGFyc2VJbnQoXG5cdFx0XHRnZXRTaW5nbGVJbnB1dChcInRvcF9uX2xhcmdlc3RfcGF0aHNcIikgfHwgXCIyMFwiLFxuXHRcdFx0MTAsXG5cdFx0KSxcblx0XHRpbmNsdWRlRXh0ZW5zaW9uczogKFxuXHRcdFx0Z2V0U2luZ2xlSW5wdXQoXCJpbmNsdWRlX2V4dGVuc2lvbnNcIikgfHwgXCIuanMsLm1qcywuY2pzXCJcblx0XHQpLnNwbGl0KFwiLFwiKSxcblx0XHRuYW1lLFxuXHRcdGFuYWx5emVyRGlyZWN0b3J5OiBnZXRTaW5nbGVJbnB1dChcImFuYWx5emVfZGlyZWN0b3J5XCIpIHx8IFwiLmFuYWx5emVyXCIsXG5cdFx0bWV0YWZpbGVzOiByYXdNZXRhZmlsZXMuc3BsaXQoXCIsXCIpLFxuXHR9O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gcnVuKGlucHV0OiBJbnB1dCA9IGdldElucHV0KCkpOiB2b2lkIHtcblx0cmVwb3J0KGlucHV0KTtcblx0Y29tcGFyZShpbnB1dCk7XG59XG5cbmlmIChpbXBvcnQubWV0YS51cmwgPT09IHBhdGhUb0ZpbGVVUkwocHJvY2Vzcy5hcmd2WzFdKS5ocmVmKSB7XG5cdHJ1bigpO1xufVxuIiwgImltcG9ydCBmcyBmcm9tIFwibm9kZTpmc1wiO1xuaW1wb3J0IHBhdGggZnJvbSBcIm5vZGU6cGF0aFwiO1xuaW1wb3J0IHR5cGUgeyBDb21wYXJlUmVzdWx0LCBJbnB1dCwgUmVwb3J0LCBUcmVlTWFwTm9kZSB9IGZyb20gXCIuL3R5cGVzXCI7XG5pbXBvcnQgeyBsb2FkQW5hbHlzaXNKc29uLCBsb2FkTWV0YUZpbGUgfSBmcm9tIFwiLi91dGlsc1wiO1xuXG5leHBvcnQgZnVuY3Rpb24gY29tcGFyZShpbnB1dDogSW5wdXQpOiB2b2lkIHtcblx0bGV0IGhhc0FueUNoYW5nZSA9IGZhbHNlO1xuXHRsZXQgb3V0cHV0ID0gYCMjIFx1RDgzRFx1RENFNiBlc2J1aWxkIEJ1bmRsZSBBbmFseXNpcyBmb3IgJHtpbnB1dC5uYW1lfVxuXG5UaGlzIGFuYWx5c2lzIHdhcyBnZW5lcmF0ZWQgYnkgW2VzYnVpbGQtYnVuZGxlLWFuYWx5emVyXShodHRwczovL2dpdGh1Yi5jb20vZXhvZWdvL2VzYnVpbGQtYnVuZGxlLWFuYWx5emVyKS4gXHVEODNFXHVERDE2XG5gO1xuXG5cdGNvbnN0IGN1cnJlbnQgPSBsb2FkQW5hbHlzaXNKc29uKFxuXHRcdHBhdGguam9pbihwcm9jZXNzLmN3ZCgpLCBpbnB1dC5hbmFseXplckRpcmVjdG9yeSwgXCJidW5kbGVfYW5hbHlzaXMuanNvblwiKSxcblx0KTtcblx0Y29uc3QgYmFzZSA9IGxvYWRCYXNlQW5hbHlzaXNKc29uKGlucHV0KTtcblxuXHRjb25zdCBmaWxlVHJlZSA9IGJ1aWxkRmlsZVRyZWUoaW5wdXQpO1xuXG5cdGNvbnN0IGFsbE91dEZpbGVzOiBzdHJpbmdbXSA9IFtcblx0XHQuLi5uZXcgU2V0KFsuLi5PYmplY3Qua2V5cyhjdXJyZW50KSwgLi4uT2JqZWN0LmtleXMoYmFzZSldKSxcblx0XS5zb3J0KCk7XG5cblx0Y29uc3QgY29tcGFyaXNvbjogQXJyYXk8Q29tcGFyZVJlc3VsdD4gPSBhbGxPdXRGaWxlcy5tYXAoKG91dGZpbGUpID0+IHtcblx0XHRjb25zdCBjdXJyZW50U3RhdHMgPSBjdXJyZW50W291dGZpbGVdO1xuXHRcdGNvbnN0IGJhc2VTdGF0cyA9IGJhc2Vbb3V0ZmlsZV07XG5cblx0XHRpZiAoIWN1cnJlbnRTdGF0cykge1xuXHRcdFx0aGFzQW55Q2hhbmdlID0gdHJ1ZTtcblx0XHRcdHJldHVybiB7IC4uLmJhc2VTdGF0cywgZGlmZjogLTEsIHJlbWFyazogXCJkZWxldGVkXCIsIHRyZWU6IHVuZGVmaW5lZCB9O1xuXHRcdH1cblxuXHRcdGNvbnN0IHRyZWUgPSBmaWxlVHJlZS5nZXQoXG5cdFx0XHR0cmVlS2V5KGN1cnJlbnRTdGF0cy5tZXRhZmlsZSwgY3VycmVudFN0YXRzLm91dGZpbGUpLFxuXHRcdCk7XG5cdFx0aWYgKCFiYXNlU3RhdHMpIHtcblx0XHRcdGhhc0FueUNoYW5nZSA9IHRydWU7XG5cdFx0XHRyZXR1cm4geyAuLi5jdXJyZW50U3RhdHMsIGRpZmY6IC0xLCByZW1hcms6IFwiYWRkZWRcIiwgdHJlZSB9O1xuXHRcdH1cblxuXHRcdGNvbnN0IGRpZmYgPSBjdXJyZW50U3RhdHMuYnl0ZXMgLSBiYXNlU3RhdHMuYnl0ZXM7XG5cdFx0aWYgKGRpZmYgIT09IDApIHtcblx0XHRcdGhhc0FueUNoYW5nZSA9IHRydWU7XG5cdFx0fVxuXHRcdHJldHVybiB7XG5cdFx0XHQuLi5jdXJyZW50U3RhdHMsXG5cdFx0XHRkaWZmLFxuXHRcdFx0dHJlZSxcblx0XHRcdHJlbWFyazogTWF0aC5zaWduKGRpZmYpID8gXCJpbmNyZWFzZWRcIiA6IFwiZGVjcmVhc2VkXCIsXG5cdFx0fTtcblx0fSk7XG5cblx0aWYgKGhhc0FueUNoYW5nZSkge1xuXHRcdG91dHB1dCArPSBtYXJrZG93blRhYmxlKGNvbXBhcmlzb24sIGlucHV0LnBlcmNlbnRFeHRyYUF0dGVudGlvbik7XG5cdFx0b3V0cHV0ICs9IGZpbGVTaXplVGFibGUoY29tcGFyaXNvbiwgaW5wdXQudG9wTkxhcmdlc3RQYXRocyk7XG5cdFx0b3V0cHV0ICs9IGRldGFpbChpbnB1dCk7XG5cdH0gZWxzZSB7XG5cdFx0b3V0cHV0ICs9IFwiVGhpcyBQUiBpbnRyb2R1Y2VkIG5vIGNoYW5nZXMgdG8gdGhlIGVzYnVpbGQgYnVuZGxlISBcdUQ4M0RcdURFNENcIjtcblx0fVxuXG5cdC8vIHdlIGFkZCB0aGlzIHRhZyBzbyB0aGF0IG91ciBhY3Rpb24gY2FuIGJlIGFibGUgdG8gZWFzaWx5IGFuZFxuXHQvLyBjb25zaXN0ZW50bHkgZmluZCB0aGUgcmlnaHQgY29tbWVudCB0byBlZGl0IGFzIG1vcmUgY29tbWl0cyBhcmUgcHVzaGVkLlxuXHRvdXRwdXQgKz0gYDwhLS0gX19FU0JVSUxEX0JVTkRMRV8ke2lucHV0Lm5hbWV9IC0tPmA7XG5cblx0d3JpdGVDb21tZW50KGlucHV0LCBvdXRwdXQpO1xufVxuXG5mdW5jdGlvbiB0cmVlS2V5KG1ldGFmaWxlOiBzdHJpbmcsIG91dGZpbGU6IHN0cmluZyk6IHN0cmluZyB7XG5cdHJldHVybiBgJHttZXRhZmlsZX0gLT4gJHtvdXRmaWxlfWA7XG59XG5cbi8vIFdyaXRlIHRoZSBvdXRwdXQgdG8gYSBmaWxlIHdoaWNoIGlzIGxhdGVyIHJlYWQgaW5cbi8vIGFzIGNvbW1lbnQgY29udGVudHMgYnkgdGhlIGFjdGlvbnMgd29ya2Zsb3cuXG5mdW5jdGlvbiB3cml0ZUNvbW1lbnQoaW5wdXQ6IElucHV0LCBvdXRwdXQ6IHN0cmluZyk6IHZvaWQge1xuXHRmcy5ta2RpclN5bmMocGF0aC5qb2luKHByb2Nlc3MuY3dkKCksIGlucHV0LmFuYWx5emVyRGlyZWN0b3J5KSwge1xuXHRcdHJlY3Vyc2l2ZTogdHJ1ZSxcblx0fSk7XG5cdGZzLndyaXRlRmlsZVN5bmMoXG5cdFx0cGF0aC5qb2luKFxuXHRcdFx0cHJvY2Vzcy5jd2QoKSxcblx0XHRcdGlucHV0LmFuYWx5emVyRGlyZWN0b3J5LFxuXHRcdFx0XCJidW5kbGVfYW5hbHlzaXNfY29tbWVudC50eHRcIixcblx0XHQpLFxuXHRcdG91dHB1dC50cmltKCksXG5cdCk7XG59XG5cbmZ1bmN0aW9uIGRldGFpbChpbnB1dDogSW5wdXQpOiBzdHJpbmcge1xuXHRpZiAoIWlucHV0LnNob3dEZXRhaWxzKSB7XG5cdFx0cmV0dXJuIFwiXCI7XG5cdH1cblx0cmV0dXJuIGBcXG48ZGV0YWlscz5cbjxzdW1tYXJ5PkRldGFpbHM8L3N1bW1hcnk+XG48cD5OZXh0IHRvIHRoZSBzaXplIGlzIGhvdyBtdWNoIHRoZSBzaXplIGhhcyBpbmNyZWFzZWQgb3IgZGVjcmVhc2VkIGNvbXBhcmVkIHdpdGggdGhlIGJhc2UgYnJhbmNoIG9mIHRoaXMgUFIuPC9wPlxuPHVsPlxuPGxpPlx1MjAzQ1x1RkUwRjogU2l6ZSBpbmNyZWFzZWQgYnkgJHtpbnB1dC5wZXJjZW50RXh0cmFBdHRlbnRpb259JSBvciBtb3JlLiBTcGVjaWFsIGF0dGVudGlvbiBzaG91bGQgYmUgZ2l2ZW4gdG8gdGhpcy48L2xpPlxuPGxpPlx1MjZBMFx1RkUwRjogU2l6ZSBpbmNyZWFzZWQgaW4gYWNjZXB0YWJsZSByYW5nZSAobG93ZXIgdGhhbiAke2lucHV0LnBlcmNlbnRFeHRyYUF0dGVudGlvbn0lKS48L2xpPlxuPGxpPlx1MjcwNTogTm8gY2hhbmdlIG9yIGV2ZW4gZG93bnNpemVkLjwvbGk+XG48bGk+XHVEODNEXHVEREQxXHVGRTBGOiBUaGUgb3V0IGZpbGUgaXMgZGVsZXRlZDogbm90IGZvdW5kIGluIGJhc2UgYnJhbmNoLjwvbGk+XG48bGk+XHVEODNDXHVERDk1OiBUaGUgb3V0IGZpbGUgaXMgbmV3bHkgZm91bmQ6IHdpbGwgYmUgYWRkZWQgdG8gYmFzZSBicmFuY2guPC9saT5cbjwvdWw+XG48L2RldGFpbHM+XFxuYDtcbn1cblxuZnVuY3Rpb24gbG9hZEJhc2VBbmFseXNpc0pzb24oaW5wdXQ6IElucHV0KTogUmVwb3J0IHtcblx0dHJ5IHtcblx0XHRyZXR1cm4gbG9hZEFuYWx5c2lzSnNvbihcblx0XHRcdHBhdGguam9pbihcblx0XHRcdFx0cHJvY2Vzcy5jd2QoKSxcblx0XHRcdFx0aW5wdXQuYW5hbHl6ZXJEaXJlY3RvcnksXG5cdFx0XHRcdFwiYmFzZS9idW5kbGUvYnVuZGxlX2FuYWx5c2lzLmpzb25cIixcblx0XHRcdCksXG5cdFx0KTtcblx0fSBjYXRjaCAoZSkge1xuXHRcdC8vIEVtcHR5IGlmIG5vIGJhc2UgYW5hbHlzaXMgZm91bmQuXG5cdFx0Ly8gVGhpcyBpcyBhIGNhc2Ugd2hlbiBhbmFseXplciBpcyBmaXJzdCBzZXQgdXAgb3IgYWxsIGFydGlmYWN0cyBhcmUgZXhwaXJlZC5cblx0XHRyZXR1cm4ge307XG5cdH1cbn1cblxuZnVuY3Rpb24gYnVpbGRGaWxlVHJlZShpbnB1dDogSW5wdXQpIHtcblx0ZnVuY3Rpb24gYnVpbGRSb290KFxuXHRcdGlucHV0OiBSZWNvcmQ8c3RyaW5nLCB7IGJ5dGVzSW5PdXRwdXQ6IG51bWJlciB9Pixcblx0KTogVHJlZU1hcE5vZGUge1xuXHRcdGNvbnN0IHJvb3Q6IFRyZWVNYXBOb2RlID0geyBuYW1lOiBcIlwiLCBwYXRoOiBcIlwiLCB2YWx1ZTogMCwgY2hpbGRyZW46IFtdIH07XG5cdFx0Zm9yIChjb25zdCBbZmlsZVBhdGgsIHsgYnl0ZXNJbk91dHB1dCB9XSBvZiBPYmplY3QuZW50cmllcyhpbnB1dCkpIHtcblx0XHRcdGNvbnN0IGRpcmVjdG9yaWVzID0gZmlsZVBhdGguc3BsaXQoXCIvXCIpO1xuXHRcdFx0YnVpbGROb2RlKHJvb3QsIGRpcmVjdG9yaWVzLCBieXRlc0luT3V0cHV0KTtcblx0XHR9XG5cdFx0cmV0dXJuIHJvb3Q7XG5cdH1cblxuXHRmdW5jdGlvbiBidWlsZE5vZGUoXG5cdFx0bm9kZTogVHJlZU1hcE5vZGUsXG5cdFx0cGF0aHM6IEFycmF5PHN0cmluZz4sXG5cdFx0dmFsdWU6IG51bWJlcixcblx0KTogdm9pZCB7XG5cdFx0Y29uc3QgZmlyc3QgPSBwYXRocy5zaGlmdCgpO1xuXHRcdGlmIChmaXJzdCA9PT0gdW5kZWZpbmVkKSB7XG5cdFx0XHQvLyBsZWFmIG5vZGUgKGZpbGUpXG5cdFx0XHRub2RlLnZhbHVlICs9IHZhbHVlO1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblx0XHRsZXQgY2hpbGQgPSBub2RlLmNoaWxkcmVuLmZpbmQoKGNoaWxkKSA9PiBjaGlsZC5uYW1lID09PSBmaXJzdCk7XG5cdFx0aWYgKCFjaGlsZCkge1xuXHRcdFx0Y2hpbGQgPSB7XG5cdFx0XHRcdG5hbWU6IGZpcnN0LFxuXHRcdFx0XHRwYXRoOiBgJHtub2RlLnBhdGh9LyR7Zmlyc3R9YC5yZXBsYWNlKC9eXFwvLywgXCJcIiksXG5cdFx0XHRcdHZhbHVlOiAwLFxuXHRcdFx0XHRjaGlsZHJlbjogW10sXG5cdFx0XHR9O1xuXHRcdFx0bm9kZS5jaGlsZHJlbi5wdXNoKGNoaWxkKTtcblx0XHR9XG5cdFx0bm9kZS52YWx1ZSArPSB2YWx1ZTtcblx0XHRidWlsZE5vZGUoY2hpbGQsIHBhdGhzLCB2YWx1ZSk7XG5cdH1cblxuXHRjb25zdCB0cmVlcyA9IG5ldyBNYXA8c3RyaW5nLCBUcmVlTWFwTm9kZT4oKTtcblx0aWYgKGlucHV0LnRvcE5MYXJnZXN0UGF0aHMgPD0gMCkge1xuXHRcdC8vIFNraXAgYnVpbGRpbmcgdHJlZSBpZiB3ZSBkb24ndCBuZWVkIGl0LlxuXHRcdHJldHVybiB0cmVlcztcblx0fVxuXHRmb3IgKGNvbnN0IG1ldGFmaWxlIG9mIGlucHV0Lm1ldGFmaWxlcykge1xuXHRcdGNvbnN0IG1ldGFmaWxlSnNvbiA9IGxvYWRNZXRhRmlsZShwYXRoLmpvaW4ocHJvY2Vzcy5jd2QoKSwgbWV0YWZpbGUpKTtcblx0XHRmb3IgKGNvbnN0IFtvdXRmaWxlLCBidWlsZE1ldGFdIG9mIE9iamVjdC5lbnRyaWVzKG1ldGFmaWxlSnNvbi5vdXRwdXRzKSkge1xuXHRcdFx0Y29uc3QgdHJlZSA9IGJ1aWxkUm9vdChidWlsZE1ldGEuaW5wdXRzKTtcblx0XHRcdHRyZWVzLnNldCh0cmVlS2V5KG1ldGFmaWxlLCBvdXRmaWxlKSwgdHJlZSk7XG5cblx0XHRcdGZzLndyaXRlRmlsZVN5bmMoXG5cdFx0XHRcdHBhdGguam9pbihwcm9jZXNzLmN3ZCgpLCBpbnB1dC5hbmFseXplckRpcmVjdG9yeSwgXCJ0cmVlLmpzb25cIiksXG5cdFx0XHRcdEpTT04uc3RyaW5naWZ5KHRyZWUsIG51bGwsIDIpLFxuXHRcdFx0KTtcblx0XHR9XG5cdH1cblx0cmV0dXJuIHRyZWVzO1xufVxuXG5jb25zdCBzcGFjZXIgPSBcIlx1MDBBMFwiO1xuZnVuY3Rpb24gZmlsZXNpemUoYnl0ZXM6IG51bWJlcik6IHN0cmluZyB7XG5cdGNvbnN0IHNpZ24gPSBieXRlcyA8IDAgPyBcIi1cIiA6IFwiXCI7XG5cdGNvbnN0IG4gPSBNYXRoLmFicyhieXRlcyk7XG5cdGlmIChuIDwgMTAwMCkge1xuXHRcdHJldHVybiBgJHtzaWdufSR7bn0ke3NwYWNlcn1CYDtcblx0fVxuXHRpZiAobiA8IDEwMDAgKiAxMDAwKSB7XG5cdFx0cmV0dXJuIGAke3NpZ259JHsobiAvIDEwMDApLnRvRml4ZWQoMil9JHtzcGFjZXJ9S0JgO1xuXHR9XG5cdGlmIChuIDwgMTAwMCAqIDEwMDAgKiAxMDAwKSB7XG5cdFx0cmV0dXJuIGAke3NpZ259JHsobiAvIDEwMDAgLyAxMDAwKS50b0ZpeGVkKDIpfSR7c3BhY2VyfU1CYDtcblx0fVxuXHRpZiAobiA8IDEwMDAgKiAxMDAwICogMTAwMCAqIDEwMDApIHtcblx0XHRyZXR1cm4gYCR7c2lnbn0keyhuIC8gMTAwMCAvIDEwMDAgLyAxMDAwKS50b0ZpeGVkKDIpfSR7c3BhY2VyfUdCYDtcblx0fVxuXHR0aHJvdyBuZXcgRXJyb3IoXCJUb28gbGFyZ2UgZmlsZSBzaXplISEgQXJlIHlvdSBzdXJlP1wiKTtcbn1cblxuZnVuY3Rpb24gbWFya2Rvd25UYWJsZShcblx0ZGF0YTogQXJyYXk8Q29tcGFyZVJlc3VsdD4sXG5cdHJlZFRocmVzaG9sZDogbnVtYmVyLFxuKTogc3RyaW5nIHtcblx0Y29uc3Qgcm93cyA9IGRhdGFcblx0XHQubWFwKChkKSA9PiB7XG5cdFx0XHRyZXR1cm4gYCR7ZC5tZXRhZmlsZX0gfCAke2Qub3V0ZmlsZX0gfCAke3JlbmRlclNpemUoZCl9IHwgJHtyZW5kZXJOb3RlKFxuXHRcdFx0XHRkLFxuXHRcdFx0XHRyZWRUaHJlc2hvbGQsXG5cdFx0XHQpfVxcbmA7XG5cdFx0fSlcblx0XHQuam9pbihcIlwiKTtcblxuXHRyZXR1cm4gYFxuTWV0YSBGaWxlIHwgT3V0IEZpbGUgIHwgU2l6ZSAocmF3KSB8IE5vdGUgXG4tLS0tLS0tLS0tfC0tLS0tLS0tLS18LS0tLS0tLS0tLS06fC0tLS0tLVxuJHtyb3dzfWA7XG59XG5cbi8qKlxuICogRmluZCB0aGUgdG9wIE4gbGFyZ2VzdCBub2RlcyBpbiByb290IHRyZWUuXG4gKiBEaWcgbm9kZXMgdW50aWwgdGhlIGRlcHRoIG9mIDMuXG4gKi9cbmZ1bmN0aW9uIGZpbmRMYXJnZURpcmVjdG9yaWVzKHJvb3Q6IFRyZWVNYXBOb2RlLCBOOiBudW1iZXIpIHtcblx0Y29uc3Qgbm9kZXM6IFRyZWVNYXBOb2RlW10gPSBbXTtcblx0Y29uc3QgcXVldWU6IEFycmF5PHsgbm9kZTogVHJlZU1hcE5vZGU7IGRlcHRoOiBudW1iZXIgfT4gPSBbXG5cdFx0eyBub2RlOiByb290LCBkZXB0aDogMCB9LFxuXHRdO1xuXHR3aGlsZSAocXVldWUubGVuZ3RoID4gMCkge1xuXHRcdGNvbnN0IHNoaWZ0ID0gcXVldWUuc2hpZnQoKTtcblx0XHRpZiAoIXNoaWZ0KSB7XG5cdFx0XHRicmVhaztcblx0XHR9XG5cdFx0Y29uc3QgeyBub2RlLCBkZXB0aCB9ID0gc2hpZnQ7XG5cdFx0aWYgKGRlcHRoID09PSAzKSB7XG5cdFx0XHRub2Rlcy5wdXNoKG5vZGUpO1xuXHRcdFx0Y29udGludWU7XG5cdFx0fVxuXHRcdGlmIChub2RlLmNoaWxkcmVuLmxlbmd0aCA9PT0gMCkge1xuXHRcdFx0bm9kZXMucHVzaChub2RlKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0Zm9yIChjb25zdCBpdGVtIG9mIG5vZGUuY2hpbGRyZW4pIHtcblx0XHRcdFx0cXVldWUucHVzaCh7IG5vZGU6IGl0ZW0sIGRlcHRoOiBkZXB0aCArIDEgfSk7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cdGNvbnN0IGxhcmdlTm9kZXMgPSBub2Rlcy5zb3J0KChhLCBiKSA9PiBiLnZhbHVlIC0gYS52YWx1ZSkuc2xpY2UoMCwgTik7XG5cdHJldHVybiB7XG5cdFx0bGFyZ2VOb2Rlcyxcblx0XHRoYXNPdGhlcjogbm9kZXMubGVuZ3RoID4gTixcblx0fTtcbn1cblxuZnVuY3Rpb24gZml4ZWRQZXJjZW50KG46IG51bWJlciwgZDogbnVtYmVyKTogbnVtYmVyIHtcblx0cmV0dXJuIE51bWJlci5wYXJzZUZsb2F0KCgobiAvIGQpICogMTAwKS50b0ZpeGVkKDEpKTtcbn1cblxuZnVuY3Rpb24gZmlsZVNpemVUYWJsZShcblx0ZGF0YTogQXJyYXk8Q29tcGFyZVJlc3VsdD4sXG5cdHRvcE5MYXJnZXN0UGF0aHM6IG51bWJlcixcbik6IHN0cmluZyB7XG5cdGlmIChkYXRhLmxlbmd0aCA9PT0gMCB8fCB0b3BOTGFyZ2VzdFBhdGhzIDw9IDApIHtcblx0XHRyZXR1cm4gXCJcIjtcblx0fVxuXHRsZXQgb3V0cHV0ID0gXCJcIjtcblx0b3V0cHV0ICs9IFwiPGRldGFpbHM+XFxuXCI7XG5cdG91dHB1dCArPSBcIjxzdW1tYXJ5Pkxhcmdlc3QgcGF0aHM8L3N1bW1hcnk+XFxuXCI7XG5cdG91dHB1dCArPSBgVGhlc2UgdmlzdWFsaXphdGlvbiBzaG93cyB0b3AgJHt0b3BOTGFyZ2VzdFBhdGhzfSBsYXJnZXN0IHBhdGhzIGluIHRoZSBidW5kbGUuXFxuYDtcblx0Zm9yIChjb25zdCBkIG9mIGRhdGEpIHtcblx0XHRvdXRwdXQgKz0gXCJcXG5cIjtcblx0XHRvdXRwdXQgKz0gYCMjIE1ldGEgZmlsZTogJHtkLm1ldGFmaWxlfSwgT3V0IGZpbGU6ICR7ZC5vdXRmaWxlfVxcbmA7XG5cdFx0aWYgKCFkLnRyZWUpIHtcblx0XHRcdG91dHB1dCArPSBcIlx1RkUwRlx1RkUwRlx1RDgzRFx1REREMVx1RkUwRkRlbGV0ZWRcXG5cIjtcblx0XHRcdGNvbnRpbnVlO1xuXHRcdH1cblx0XHRvdXRwdXQgKz0gXCJ8IFBhdGggfCBTaXplIHxcXG5cIjtcblx0XHRvdXRwdXQgKz0gXCJ8LS0tLS0tfC0tLS0tLS18XFxuXCI7XG5cdFx0Y29uc3QgdG90YWxTaXplID0gZC50cmVlLnZhbHVlO1xuXHRcdGNvbnN0IHsgbGFyZ2VOb2RlcywgaGFzT3RoZXIgfSA9IGZpbmRMYXJnZURpcmVjdG9yaWVzKFxuXHRcdFx0ZC50cmVlLFxuXHRcdFx0dG9wTkxhcmdlc3RQYXRocyxcblx0XHQpO1xuXHRcdGZvciAoY29uc3QgeyBwYXRoLCB2YWx1ZSB9IG9mIGxhcmdlTm9kZXMpIHtcblx0XHRcdGNvbnN0IHBlcmNlbnQgPSBmaXhlZFBlcmNlbnQodmFsdWUsIHRvdGFsU2l6ZSk7XG5cdFx0XHRvdXRwdXQgKz0gYHwgJHtwYXRofSB8ICR7cmVuZGVyQmFyKHBlcmNlbnQsIHZhbHVlKX0gfFxcbmA7XG5cdFx0fVxuXHRcdGlmIChoYXNPdGhlcikge1xuXHRcdFx0Y29uc3Qgb3RoZXJTaXplID0gdG90YWxTaXplIC0gbGFyZ2VOb2Rlc1swXS52YWx1ZTtcblx0XHRcdGNvbnN0IG90aGVyUGVyY2VudCA9IGZpeGVkUGVyY2VudChvdGhlclNpemUsIHRvdGFsU2l6ZSk7XG5cdFx0XHRvdXRwdXQgKz0gYHwgKG90aGVyKSB8ICR7cmVuZGVyQmFyKG90aGVyUGVyY2VudCwgb3RoZXJTaXplKX0gfFxcbmA7XG5cdFx0fVxuXHR9XG5cdG91dHB1dCArPSBcIjwvZGV0YWlscz5cXG5cIjtcblx0cmV0dXJuIG91dHB1dDtcbn1cblxuZnVuY3Rpb24gcmVuZGVyQmFyKHBlcmNlbnQ6IG51bWJlciwgYnl0ZXM6IG51bWJlcik6IHN0cmluZyB7XG5cdGNvbnN0IGJhciA9IHByb2dyZXNzKHBlcmNlbnQgLyAxMDApO1xuXHRyZXR1cm4gYFxcJHt7XFxcXGNvbG9ye0dvbGRlbnJvZH17ICR7YmFyfSB9fX1cXCQgJHtwZXJjZW50LnRvRml4ZWQoXG5cdFx0MSxcblx0KX0lLCAke2ZpbGVzaXplKGJ5dGVzKX1gO1xufVxuXG4vLyBCbG9jayBwcm9ncmVzc2lvbiBpcyAxLzggPSAwLjEyNVxuY29uc3QgYmxvY2tzID0gW1wiXCIsIFwiXHUyNThGXCIsIFwiXHUyNThFXCIsIFwiXHUyNThEXCIsIFwiXHUyNThDXCIsIFwiXHUyNThCXCIsIFwiXHUyNThBXCIsIFwiXHUyNTg5XCIsIFwiXHUyNTg4XCJdO1xuY29uc3QgcHJvZ3Jlc3Npb24gPSAxIC8gKGJsb2Nrcy5sZW5ndGggLSAxKTtcbmZ1bmN0aW9uIHByb2dyZXNzKHZhbHVlOiBudW1iZXIsIGxlbmd0aCA9IDI1LCB2bWluID0gMC4wLCB2bWF4ID0gMS4wKSB7XG5cdGNvbnN0IHYgPSB2YWx1ZSAqIGxlbmd0aDtcblx0Y29uc3QgaW50ZWdlclBhcnQgPSBNYXRoLmZsb29yKHYpO1xuXHRjb25zdCBmcmFjdGlvbmFsUGFydCA9IHYgLSBpbnRlZ2VyUGFydDtcblx0Y29uc3QgaSA9IE1hdGgucm91bmQoXG5cdFx0KHByb2dyZXNzaW9uICogTWF0aC5mbG9vcihmcmFjdGlvbmFsUGFydCAvIHByb2dyZXNzaW9uKSkgLyBwcm9ncmVzc2lvbixcblx0KTtcblx0cmV0dXJuIFwiXHUyNTg4XCIucmVwZWF0KGludGVnZXJQYXJ0KSArIGJsb2Nrc1tpXTtcbn1cblxuZnVuY3Rpb24gcmVuZGVyU2l6ZShkOiBDb21wYXJlUmVzdWx0KTogc3RyaW5nIHtcblx0cmV0dXJuIGZpbGVzaXplKGQuYnl0ZXMpO1xufVxuXG5mdW5jdGlvbiByZW5kZXJOb3RlKGQ6IENvbXBhcmVSZXN1bHQsIHJlZFRocmVzaG9sZDogbnVtYmVyKTogc3RyaW5nIHtcblx0aWYgKGQucmVtYXJrID09PSBcImRlbGV0ZWRcIikge1xuXHRcdHJldHVybiBcIlx1RDgzRFx1REREMVx1RkUwRiBEZWxldGVkXCI7XG5cdH1cblx0aWYgKGQucmVtYXJrID09PSBcImFkZGVkXCIpIHtcblx0XHRyZXR1cm4gXCJcdUQ4M0NcdUREOTUgQWRkZWRcIjtcblx0fVxuXHRpZiAoZC5kaWZmKSB7XG5cdFx0Y29uc3QgcGVyY2VudENoYW5nZSA9IChkLmRpZmYgLyBkLmJ5dGVzKSAqIDEwMDtcblx0XHRyZXR1cm4gYCR7cmVuZGVyU3RhdHVzSW5kaWNhdG9yKHBlcmNlbnRDaGFuZ2UsIHJlZFRocmVzaG9sZCl9JHtmaWxlc2l6ZShcblx0XHRcdGQuZGlmZixcblx0XHQpfSAoJHtzaWduKHBlcmNlbnRDaGFuZ2UpfSR7cGVyY2VudENoYW5nZS50b0ZpeGVkKDEpfSUpYDtcblx0fVxuXHRyZXR1cm4gXCJcdTI3MDUgIE5vIGNoYW5nZVwiO1xufVxuXG5mdW5jdGlvbiBzaWduKG51bTogbnVtYmVyKTogc3RyaW5nIHtcblx0cmV0dXJuIG51bSA8IDAgPyBcIlwiIDogXCIrXCI7XG59XG5cbmZ1bmN0aW9uIHJlbmRlclN0YXR1c0luZGljYXRvcihcblx0cGVyY2VudENoYW5nZTogbnVtYmVyLFxuXHRyZWRUaHJlc2hvbGQ6IG51bWJlcixcbik6IHN0cmluZyB7XG5cdGxldCByZXM6IHN0cmluZztcblx0aWYgKHBlcmNlbnRDaGFuZ2UgPiAwICYmIHBlcmNlbnRDaGFuZ2UgPCByZWRUaHJlc2hvbGQpIHtcblx0XHRyZXMgPSBcIlx1MjZBMFx1RkUwRlwiO1xuXHR9IGVsc2UgaWYgKHBlcmNlbnRDaGFuZ2UgPj0gcmVkVGhyZXNob2xkKSB7XG5cdFx0cmVzID0gXCJcdTIwM0NcdUZFMEZcIjtcblx0fSBlbHNlIHtcblx0XHRyZXMgPSBcIlx1MjcwNSBcIjtcblx0fVxuXHRyZXR1cm4gYCR7cmVzfSAke3NpZ24ocGVyY2VudENoYW5nZSl9YDtcbn1cbiIsICJpbXBvcnQgZnMgZnJvbSBcIm5vZGU6ZnNcIjtcblxuaW1wb3J0IHR5cGUgeyBNZXRhZmlsZSB9IGZyb20gXCJlc2J1aWxkXCI7XG5pbXBvcnQgdHlwZSB7IFJlcG9ydCB9IGZyb20gXCIuL3R5cGVzXCI7XG5cbmZ1bmN0aW9uIGxvYWRKc29uRmlsZShwYXRoOiBzdHJpbmcpIHtcblx0cmV0dXJuIEpTT04ucGFyc2UoZnMucmVhZEZpbGVTeW5jKHBhdGgpLnRvU3RyaW5nKFwidXRmLThcIikpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gbG9hZE1ldGFGaWxlKHBhdGg6IHN0cmluZyk6IE1ldGFmaWxlIHtcblx0cmV0dXJuIGxvYWRKc29uRmlsZShwYXRoKSBhcyBNZXRhZmlsZTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGxvYWRBbmFseXNpc0pzb24ocGF0aDogc3RyaW5nKTogUmVwb3J0IHtcblx0cmV0dXJuIGxvYWRKc29uRmlsZShwYXRoKSBhcyBSZXBvcnQ7XG59XG5cbi8vIGh0dHBzOi8vZ2l0aHViLmNvbS9hY3Rpb25zL3Rvb2xraXQvYmxvYi84MWE3M2FiYThiZWRkNTMyZjZlZGRjYzQxZWQzYTBmYWQ4YjFjZmViL3BhY2thZ2VzL2NvcmUvc3JjL2NvcmUudHMjTDEyNlxuZXhwb3J0IGZ1bmN0aW9uIGdldFNpbmdsZUlucHV0KG5hbWU6IHN0cmluZyk6IHN0cmluZyB7XG5cdGNvbnN0IHZhbCA9IHByb2Nlc3MuZW52W2BJTlBVVF8ke25hbWUudG9VcHBlckNhc2UoKX1gXSB8fCBcIlwiO1xuXHRyZXR1cm4gdmFsLnRyaW0oKTtcbn1cbiIsICJpbXBvcnQgZnMgZnJvbSBcIm5vZGU6ZnNcIjtcbmltcG9ydCBwYXRoIGZyb20gXCJub2RlOnBhdGhcIjtcbmltcG9ydCBwcm9jZXNzIGZyb20gXCJub2RlOnByb2Nlc3NcIjtcblxuaW1wb3J0IHR5cGUgeyBJbnB1dCwgUmVwb3J0IH0gZnJvbSBcIi4vdHlwZXNcIjtcbmltcG9ydCB7IGxvYWRNZXRhRmlsZSB9IGZyb20gXCIuL3V0aWxzXCI7XG5cbmV4cG9ydCBmdW5jdGlvbiByZXBvcnQoaW5wdXQ6IElucHV0KTogdm9pZCB7XG5cdGNvbnN0IGFsbFBhZ2VTaXplcyA9IGdldEFsbFBhZ2VTaXplcyhpbnB1dCk7XG5cdGZzLm1rZGlyU3luYyhwYXRoLmpvaW4ocHJvY2Vzcy5jd2QoKSwgaW5wdXQuYW5hbHl6ZXJEaXJlY3RvcnkpLCB7XG5cdFx0cmVjdXJzaXZlOiB0cnVlLFxuXHR9KTtcblx0Y29uc3QgcmVzdWx0SnNvblBhdGggPSBwYXRoLmpvaW4oXG5cdFx0cHJvY2Vzcy5jd2QoKSxcblx0XHRpbnB1dC5hbmFseXplckRpcmVjdG9yeSxcblx0XHRcImJ1bmRsZV9hbmFseXNpcy5qc29uXCIsXG5cdCk7XG5cdGZzLndyaXRlRmlsZVN5bmMocmVzdWx0SnNvblBhdGgsIEpTT04uc3RyaW5naWZ5KGFsbFBhZ2VTaXplcywgbnVsbCwgMikpO1xuXHRjb25zb2xlLmxvZyhgV3JvdGUgJHtyZXN1bHRKc29uUGF0aH1gKTtcbn1cblxuZnVuY3Rpb24gZ2V0QWxsUGFnZVNpemVzKGlucHV0OiBJbnB1dCk6IFJlcG9ydCB7XG5cdGNvbnN0IGFjYzogUmVwb3J0ID0ge307XG5cdHJldHVybiBpbnB1dC5tZXRhZmlsZXMucmVkdWNlKChhY2MsIG1ldGFmaWxlKSA9PiB7XG5cdFx0Y29uc3QgbWV0YUZpbGVQYXRoID0gcGF0aC5qb2luKHByb2Nlc3MuY3dkKCksIG1ldGFmaWxlKTtcblx0XHR0cnkge1xuXHRcdFx0ZnMuYWNjZXNzU3luYyhtZXRhRmlsZVBhdGgsIGZzLmNvbnN0YW50cy5SX09LKTtcblx0XHR9IGNhdGNoIChlcnIpIHtcblx0XHRcdGNvbnNvbGUuZXJyb3IoXG5cdFx0XHRcdGBObyBtZXRhIGZpbGUgZm91bmQgYXQgXCIke21ldGFGaWxlUGF0aH1cIiAtIGEgcGF0aCB0byBtZXRhIGZpbGUgbWF5IGJlIHdyb25nLCBvciBlc2J1aWxkIGlzIG5vdCBleGVjdXRlZC5gLFxuXHRcdFx0KTtcblx0XHRcdHByb2Nlc3MuZXhpdCgxKTtcblx0XHR9XG5cblx0XHRjb25zdCBtZXRhRmlsZUpzb24gPSBsb2FkTWV0YUZpbGUobWV0YUZpbGVQYXRoKTtcblx0XHRPYmplY3QuZW50cmllcyhtZXRhRmlsZUpzb24ub3V0cHV0cykucmVkdWNlKChhY2MsIG91dHB1dCkgPT4ge1xuXHRcdFx0Y29uc3QgW291dGZpbGUsIGJ1aWxkTWV0YV0gPSBvdXRwdXQ7XG5cdFx0XHRpZiAoXG5cdFx0XHRcdCFpbnB1dC5pbmNsdWRlRXh0ZW5zaW9ucy5zb21lKChleHQpID0+XG5cdFx0XHRcdFx0b3V0ZmlsZS50b0xvd2VyQ2FzZSgpLmVuZHNXaXRoKGV4dCksXG5cdFx0XHRcdClcblx0XHRcdCkge1xuXHRcdFx0XHRyZXR1cm4gYWNjO1xuXHRcdFx0fVxuXHRcdFx0YWNjW2Ake21ldGFmaWxlfSAtPiAke291dGZpbGV9YF0gPSB7XG5cdFx0XHRcdGJ5dGVzOiBidWlsZE1ldGEuYnl0ZXMsXG5cdFx0XHRcdG1ldGFmaWxlLFxuXHRcdFx0XHRvdXRmaWxlLFxuXHRcdFx0fTtcblx0XHRcdHJldHVybiBhY2M7XG5cdFx0fSwgYWNjKTtcblx0XHRyZXR1cm4gYWNjO1xuXHR9LCBhY2MpO1xufVxuIl0sCiAgIm1hcHBpbmdzIjogIjtBQUFBLFNBQVMscUJBQXFCOzs7QUNBOUIsT0FBT0EsU0FBUTtBQUNmLE9BQU8sVUFBVTs7O0FDRGpCLE9BQU8sUUFBUTtBQUtmLFNB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
+//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vc3JjL2luZGV4LnRzIiwgIi4uL3NyYy9jb21wYXJlLnRzIiwgIi4uL3NyYy9yZXBvcnQudHMiLCAiLi4vc3JjL3V0aWxzLnRzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWyJpbXBvcnQgeyBwYXRoVG9GaWxlVVJMIH0gZnJvbSBcIm5vZGU6dXJsXCI7XG5pbXBvcnQgeyBjb21wYXJlIH0gZnJvbSBcIi4vY29tcGFyZVwiO1xuaW1wb3J0IHsgcmVwb3J0IH0gZnJvbSBcIi4vcmVwb3J0XCI7XG5pbXBvcnQgdHlwZSB7IElucHV0IH0gZnJvbSBcIi4vdHlwZXNcIjtcbmltcG9ydCB7IGdldFNpbmdsZUlucHV0IH0gZnJvbSBcIi4vdXRpbHNcIjtcblxuZnVuY3Rpb24gZ2V0SW5wdXQoKTogSW5wdXQge1xuXHRjb25zdCByYXdNZXRhZmlsZXMgPSBnZXRTaW5nbGVJbnB1dChcIm1ldGFmaWxlc1wiKTtcblx0aWYgKCFyYXdNZXRhZmlsZXMpIHtcblx0XHR0aHJvdyBuZXcgRXJyb3IoXCJtZXRhZmlsZXMgaXMgbm90IHNwZWNpZmllZFwiKTtcblx0fVxuXHRjb25zdCBuYW1lID0gZ2V0U2luZ2xlSW5wdXQoXCJuYW1lXCIpO1xuXHRpZiAoIW5hbWUpIHtcblx0XHR0aHJvdyBuZXcgRXJyb3IoXCJuYW1lIGlzIG5vdCBzcGVjaWZpZWRcIik7XG5cdH1cblx0cmV0dXJuIHtcblx0XHRwZXJjZW50RXh0cmFBdHRlbnRpb246IE51bWJlci5wYXJzZUludChcblx0XHRcdGdldFNpbmdsZUlucHV0KFwicGVyY2VudF9leHRyYV9hdHRlbnRpb25cIikgfHwgXCIyMFwiLFxuXHRcdFx0MTAsXG5cdFx0KSxcblx0XHRzaG93RGV0YWlsczogW1widHJ1ZVwiLCBcIlRydWVcIiwgXCJUUlVFXCJdLmluY2x1ZGVzKFxuXHRcdFx0Z2V0U2luZ2xlSW5wdXQoXCJzaG93X2RldGFpbHNcIikgfHwgXCJ0cnVlXCIsXG5cdFx0KSxcblx0XHR0b3BOTGFyZ2VzdFBhdGhzOiBOdW1iZXIucGFyc2VJbnQoXG5cdFx0XHRnZXRTaW5nbGVJbnB1dChcInRvcF9uX2xhcmdlc3RfcGF0aHNcIikgfHwgXCIyMFwiLFxuXHRcdFx0MTAsXG5cdFx0KSxcblx0XHRpbmNsdWRlRXh0ZW5zaW9uczogKFxuXHRcdFx0Z2V0U2luZ2xlSW5wdXQoXCJpbmNsdWRlX2V4dGVuc2lvbnNcIikgfHwgXCIuanMsLm1qcywuY2pzXCJcblx0XHQpLnNwbGl0KFwiLFwiKSxcblx0XHRuYW1lLFxuXHRcdGFuYWx5emVyRGlyZWN0b3J5OiBnZXRTaW5nbGVJbnB1dChcImFuYWx5emVfZGlyZWN0b3J5XCIpIHx8IFwiLmFuYWx5emVyXCIsXG5cdFx0bWV0YWZpbGVzOiByYXdNZXRhZmlsZXMuc3BsaXQoXCIsXCIpLFxuXHR9O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gcnVuKGlucHV0OiBJbnB1dCA9IGdldElucHV0KCkpOiB2b2lkIHtcblx0cmVwb3J0KGlucHV0KTtcblx0Y29tcGFyZShpbnB1dCk7XG59XG5cbmlmIChpbXBvcnQubWV0YS51cmwgPT09IHBhdGhUb0ZpbGVVUkwocHJvY2Vzcy5hcmd2WzFdKS5ocmVmKSB7XG5cdHJ1bigpO1xufVxuIiwgImltcG9ydCBmcyBmcm9tIFwibm9kZTpmc1wiO1xuaW1wb3J0IHBhdGggZnJvbSBcIm5vZGU6cGF0aFwiO1xuaW1wb3J0IHsgZmluZE1ldGFmaWxlcyB9IGZyb20gXCIuL3JlcG9ydFwiO1xuaW1wb3J0IHR5cGUgeyBDb21wYXJlUmVzdWx0LCBJbnB1dCwgUmVwb3J0LCBUcmVlTWFwTm9kZSB9IGZyb20gXCIuL3R5cGVzXCI7XG5pbXBvcnQgeyBsb2FkQW5hbHlzaXNKc29uLCBsb2FkTWV0YUZpbGUgfSBmcm9tIFwiLi91dGlsc1wiO1xuXG5leHBvcnQgZnVuY3Rpb24gY29tcGFyZShpbnB1dDogSW5wdXQpOiB2b2lkIHtcblx0bGV0IGhhc0FueUNoYW5nZSA9IGZhbHNlO1xuXHRsZXQgb3V0cHV0ID0gYCMjIFx1RDgzRFx1RENFNiBlc2J1aWxkIEJ1bmRsZSBBbmFseXNpcyBmb3IgJHtpbnB1dC5uYW1lfVxuXG5UaGlzIGFuYWx5c2lzIHdhcyBnZW5lcmF0ZWQgYnkgW2VzYnVpbGQtYnVuZGxlLWFuYWx5emVyXShodHRwczovL2dpdGh1Yi5jb20vZXhvZWdvL2VzYnVpbGQtYnVuZGxlLWFuYWx5emVyKS4gXHVEODNFXHVERDE2XG5gO1xuXG5cdGNvbnN0IGN1cnJlbnQgPSBsb2FkQW5hbHlzaXNKc29uKFxuXHRcdHBhdGguam9pbihwcm9jZXNzLmN3ZCgpLCBpbnB1dC5hbmFseXplckRpcmVjdG9yeSwgXCJidW5kbGVfYW5hbHlzaXMuanNvblwiKSxcblx0KTtcblx0Y29uc3QgYmFzZSA9IGxvYWRCYXNlQW5hbHlzaXNKc29uKGlucHV0KTtcblxuXHRjb25zdCBmaWxlVHJlZSA9IGJ1aWxkRmlsZVRyZWUoaW5wdXQpO1xuXG5cdGNvbnN0IGFsbE91dEZpbGVzOiBzdHJpbmdbXSA9IFtcblx0XHQuLi5uZXcgU2V0KFsuLi5PYmplY3Qua2V5cyhjdXJyZW50KSwgLi4uT2JqZWN0LmtleXMoYmFzZSldKSxcblx0XS5zb3J0KCk7XG5cblx0Y29uc3QgY29tcGFyaXNvbjogQXJyYXk8Q29tcGFyZVJlc3VsdD4gPSBhbGxPdXRGaWxlcy5tYXAoKG91dGZpbGUpID0+IHtcblx0XHRjb25zdCBjdXJyZW50U3RhdHMgPSBjdXJyZW50W291dGZpbGVdO1xuXHRcdGNvbnN0IGJhc2VTdGF0cyA9IGJhc2Vbb3V0ZmlsZV07XG5cblx0XHRpZiAoIWN1cnJlbnRTdGF0cykge1xuXHRcdFx0aGFzQW55Q2hhbmdlID0gdHJ1ZTtcblx0XHRcdHJldHVybiB7IC4uLmJhc2VTdGF0cywgZGlmZjogLTEsIHJlbWFyazogXCJkZWxldGVkXCIsIHRyZWU6IHVuZGVmaW5lZCB9O1xuXHRcdH1cblxuXHRcdGNvbnN0IHRyZWUgPSBmaWxlVHJlZS5nZXQoXG5cdFx0XHR0cmVlS2V5KGN1cnJlbnRTdGF0cy5tZXRhZmlsZSwgY3VycmVudFN0YXRzLm91dGZpbGUpLFxuXHRcdCk7XG5cdFx0aWYgKCFiYXNlU3RhdHMpIHtcblx0XHRcdGhhc0FueUNoYW5nZSA9IHRydWU7XG5cdFx0XHRyZXR1cm4geyAuLi5jdXJyZW50U3RhdHMsIGRpZmY6IC0xLCByZW1hcms6IFwiYWRkZWRcIiwgdHJlZSB9O1xuXHRcdH1cblxuXHRcdGNvbnN0IGRpZmYgPSBjdXJyZW50U3RhdHMuYnl0ZXMgLSBiYXNlU3RhdHMuYnl0ZXM7XG5cdFx0aWYgKGRpZmYgIT09IDApIHtcblx0XHRcdGhhc0FueUNoYW5nZSA9IHRydWU7XG5cdFx0fVxuXHRcdHJldHVybiB7XG5cdFx0XHQuLi5jdXJyZW50U3RhdHMsXG5cdFx0XHRkaWZmLFxuXHRcdFx0dHJlZSxcblx0XHRcdHJlbWFyazogTWF0aC5zaWduKGRpZmYpID8gXCJpbmNyZWFzZWRcIiA6IFwiZGVjcmVhc2VkXCIsXG5cdFx0fTtcblx0fSk7XG5cblx0aWYgKGhhc0FueUNoYW5nZSkge1xuXHRcdG91dHB1dCArPSBtYXJrZG93blRhYmxlKGNvbXBhcmlzb24sIGlucHV0LnBlcmNlbnRFeHRyYUF0dGVudGlvbik7XG5cdFx0b3V0cHV0ICs9IGZpbGVTaXplVGFibGUoY29tcGFyaXNvbiwgaW5wdXQudG9wTkxhcmdlc3RQYXRocyk7XG5cdFx0b3V0cHV0ICs9IGRldGFpbChpbnB1dCk7XG5cdH0gZWxzZSB7XG5cdFx0b3V0cHV0ICs9IFwiVGhpcyBQUiBpbnRyb2R1Y2VkIG5vIGNoYW5nZXMgdG8gdGhlIGVzYnVpbGQgYnVuZGxlISBcdUQ4M0RcdURFNENcIjtcblx0fVxuXG5cdC8vIHdlIGFkZCB0aGlzIHRhZyBzbyB0aGF0IG91ciBhY3Rpb24gY2FuIGJlIGFibGUgdG8gZWFzaWx5IGFuZFxuXHQvLyBjb25zaXN0ZW50bHkgZmluZCB0aGUgcmlnaHQgY29tbWVudCB0byBlZGl0IGFzIG1vcmUgY29tbWl0cyBhcmUgcHVzaGVkLlxuXHRvdXRwdXQgKz0gYDwhLS0gX19FU0JVSUxEX0JVTkRMRV8ke2lucHV0Lm5hbWV9IC0tPmA7XG5cblx0d3JpdGVDb21tZW50KGlucHV0LCBvdXRwdXQpO1xufVxuXG5mdW5jdGlvbiB0cmVlS2V5KG1ldGFmaWxlOiBzdHJpbmcsIG91dGZpbGU6IHN0cmluZyk6IHN0cmluZyB7XG5cdHJldHVybiBgJHttZXRhZmlsZX0gLT4gJHtvdXRmaWxlfWA7XG59XG5cbi8vIFdyaXRlIHRoZSBvdXRwdXQgdG8gYSBmaWxlIHdoaWNoIGlzIGxhdGVyIHJlYWQgaW5cbi8vIGFzIGNvbW1lbnQgY29udGVudHMgYnkgdGhlIGFjdGlvbnMgd29ya2Zsb3cuXG5mdW5jdGlvbiB3cml0ZUNvbW1lbnQoaW5wdXQ6IElucHV0LCBvdXRwdXQ6IHN0cmluZyk6IHZvaWQge1xuXHRmcy5ta2RpclN5bmMocGF0aC5qb2luKHByb2Nlc3MuY3dkKCksIGlucHV0LmFuYWx5emVyRGlyZWN0b3J5KSwge1xuXHRcdHJlY3Vyc2l2ZTogdHJ1ZSxcblx0fSk7XG5cdGZzLndyaXRlRmlsZVN5bmMoXG5cdFx0cGF0aC5qb2luKFxuXHRcdFx0cHJvY2Vzcy5jd2QoKSxcblx0XHRcdGlucHV0LmFuYWx5emVyRGlyZWN0b3J5LFxuXHRcdFx0XCJidW5kbGVfYW5hbHlzaXNfY29tbWVudC50eHRcIixcblx0XHQpLFxuXHRcdG91dHB1dC50cmltKCksXG5cdCk7XG59XG5cbmZ1bmN0aW9uIGRldGFpbChpbnB1dDogSW5wdXQpOiBzdHJpbmcge1xuXHRpZiAoIWlucHV0LnNob3dEZXRhaWxzKSB7XG5cdFx0cmV0dXJuIFwiXCI7XG5cdH1cblx0cmV0dXJuIGBcXG48ZGV0YWlscz5cbjxzdW1tYXJ5PkRldGFpbHM8L3N1bW1hcnk+XG48cD5OZXh0IHRvIHRoZSBzaXplIGlzIGhvdyBtdWNoIHRoZSBzaXplIGhhcyBpbmNyZWFzZWQgb3IgZGVjcmVhc2VkIGNvbXBhcmVkIHdpdGggdGhlIGJhc2UgYnJhbmNoIG9mIHRoaXMgUFIuPC9wPlxuPHVsPlxuPGxpPlx1MjAzQ1x1RkUwRjogU2l6ZSBpbmNyZWFzZWQgYnkgJHtpbnB1dC5wZXJjZW50RXh0cmFBdHRlbnRpb259JSBvciBtb3JlLiBTcGVjaWFsIGF0dGVudGlvbiBzaG91bGQgYmUgZ2l2ZW4gdG8gdGhpcy48L2xpPlxuPGxpPlx1MjZBMFx1RkUwRjogU2l6ZSBpbmNyZWFzZWQgaW4gYWNjZXB0YWJsZSByYW5nZSAobG93ZXIgdGhhbiAke2lucHV0LnBlcmNlbnRFeHRyYUF0dGVudGlvbn0lKS48L2xpPlxuPGxpPlx1MjcwNTogTm8gY2hhbmdlIG9yIGV2ZW4gZG93bnNpemVkLjwvbGk+XG48bGk+XHVEODNEXHVEREQxXHVGRTBGOiBUaGUgb3V0IGZpbGUgaXMgZGVsZXRlZDogbm90IGZvdW5kIGluIGJhc2UgYnJhbmNoLjwvbGk+XG48bGk+XHVEODNDXHVERDk1OiBUaGUgb3V0IGZpbGUgaXMgbmV3bHkgZm91bmQ6IHdpbGwgYmUgYWRkZWQgdG8gYmFzZSBicmFuY2guPC9saT5cbjwvdWw+XG48L2RldGFpbHM+XFxuYDtcbn1cblxuZnVuY3Rpb24gbG9hZEJhc2VBbmFseXNpc0pzb24oaW5wdXQ6IElucHV0KTogUmVwb3J0IHtcblx0dHJ5IHtcblx0XHRyZXR1cm4gbG9hZEFuYWx5c2lzSnNvbihcblx0XHRcdHBhdGguam9pbihcblx0XHRcdFx0cHJvY2Vzcy5jd2QoKSxcblx0XHRcdFx0aW5wdXQuYW5hbHl6ZXJEaXJlY3RvcnksXG5cdFx0XHRcdFwiYmFzZS9idW5kbGUvYnVuZGxlX2FuYWx5c2lzLmpzb25cIixcblx0XHRcdCksXG5cdFx0KTtcblx0fSBjYXRjaCAoZSkge1xuXHRcdC8vIEVtcHR5IGlmIG5vIGJhc2UgYW5hbHlzaXMgZm91bmQuXG5cdFx0Ly8gVGhpcyBpcyBhIGNhc2Ugd2hlbiBhbmFseXplciBpcyBmaXJzdCBzZXQgdXAgb3IgYWxsIGFydGlmYWN0cyBhcmUgZXhwaXJlZC5cblx0XHRyZXR1cm4ge307XG5cdH1cbn1cblxuZnVuY3Rpb24gYnVpbGRGaWxlVHJlZShpbnB1dDogSW5wdXQpIHtcblx0ZnVuY3Rpb24gYnVpbGRSb290KFxuXHRcdGlucHV0OiBSZWNvcmQ8c3RyaW5nLCB7IGJ5dGVzSW5PdXRwdXQ6IG51bWJlciB9Pixcblx0KTogVHJlZU1hcE5vZGUge1xuXHRcdGNvbnN0IHJvb3Q6IFRyZWVNYXBOb2RlID0geyBuYW1lOiBcIlwiLCBwYXRoOiBcIlwiLCB2YWx1ZTogMCwgY2hpbGRyZW46IFtdIH07XG5cdFx0Zm9yIChjb25zdCBbZmlsZVBhdGgsIHsgYnl0ZXNJbk91dHB1dCB9XSBvZiBPYmplY3QuZW50cmllcyhpbnB1dCkpIHtcblx0XHRcdGNvbnN0IGRpcmVjdG9yaWVzID0gZmlsZVBhdGguc3BsaXQoXCIvXCIpO1xuXHRcdFx0YnVpbGROb2RlKHJvb3QsIGRpcmVjdG9yaWVzLCBieXRlc0luT3V0cHV0KTtcblx0XHR9XG5cdFx0cmV0dXJuIHJvb3Q7XG5cdH1cblxuXHRmdW5jdGlvbiBidWlsZE5vZGUoXG5cdFx0bm9kZTogVHJlZU1hcE5vZGUsXG5cdFx0cGF0aHM6IEFycmF5PHN0cmluZz4sXG5cdFx0dmFsdWU6IG51bWJlcixcblx0KTogdm9pZCB7XG5cdFx0Y29uc3QgZmlyc3QgPSBwYXRocy5zaGlmdCgpO1xuXHRcdGlmIChmaXJzdCA9PT0gdW5kZWZpbmVkKSB7XG5cdFx0XHQvLyBsZWFmIG5vZGUgKGZpbGUpXG5cdFx0XHRub2RlLnZhbHVlICs9IHZhbHVlO1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblx0XHRsZXQgY2hpbGQgPSBub2RlLmNoaWxkcmVuLmZpbmQoKGNoaWxkKSA9PiBjaGlsZC5uYW1lID09PSBmaXJzdCk7XG5cdFx0aWYgKCFjaGlsZCkge1xuXHRcdFx0Y2hpbGQgPSB7XG5cdFx0XHRcdG5hbWU6IGZpcnN0LFxuXHRcdFx0XHRwYXRoOiBgJHtub2RlLnBhdGh9LyR7Zmlyc3R9YC5yZXBsYWNlKC9eXFwvLywgXCJcIiksXG5cdFx0XHRcdHZhbHVlOiAwLFxuXHRcdFx0XHRjaGlsZHJlbjogW10sXG5cdFx0XHR9O1xuXHRcdFx0bm9kZS5jaGlsZHJlbi5wdXNoKGNoaWxkKTtcblx0XHR9XG5cdFx0bm9kZS52YWx1ZSArPSB2YWx1ZTtcblx0XHRidWlsZE5vZGUoY2hpbGQsIHBhdGhzLCB2YWx1ZSk7XG5cdH1cblxuXHRjb25zdCB0cmVlcyA9IG5ldyBNYXA8c3RyaW5nLCBUcmVlTWFwTm9kZT4oKTtcblx0aWYgKGlucHV0LnRvcE5MYXJnZXN0UGF0aHMgPD0gMCkge1xuXHRcdC8vIFNraXAgYnVpbGRpbmcgdHJlZSBpZiB3ZSBkb24ndCBuZWVkIGl0LlxuXHRcdHJldHVybiB0cmVlcztcblx0fVxuXHRmb3IgKGNvbnN0IHsgcmVsYXRpdmVQYXRoLCBhYnNvbHV0ZVBhdGggfSBvZiBmaW5kTWV0YWZpbGVzKGlucHV0KSkge1xuXHRcdGNvbnN0IG1ldGFmaWxlSnNvbiA9IGxvYWRNZXRhRmlsZShhYnNvbHV0ZVBhdGgpO1xuXHRcdGZvciAoY29uc3QgW291dGZpbGUsIGJ1aWxkTWV0YV0gb2YgT2JqZWN0LmVudHJpZXMobWV0YWZpbGVKc29uLm91dHB1dHMpKSB7XG5cdFx0XHRjb25zdCB0cmVlID0gYnVpbGRSb290KGJ1aWxkTWV0YS5pbnB1dHMpO1xuXHRcdFx0dHJlZXMuc2V0KHRyZWVLZXkocmVsYXRpdmVQYXRoLCBvdXRmaWxlKSwgdHJlZSk7XG5cblx0XHRcdGZzLndyaXRlRmlsZVN5bmMoXG5cdFx0XHRcdHBhdGguam9pbihwcm9jZXNzLmN3ZCgpLCBpbnB1dC5hbmFseXplckRpcmVjdG9yeSwgXCJ0cmVlLmpzb25cIiksXG5cdFx0XHRcdEpTT04uc3RyaW5naWZ5KHRyZWUsIG51bGwsIDIpLFxuXHRcdFx0KTtcblx0XHR9XG5cdH1cblx0cmV0dXJuIHRyZWVzO1xufVxuXG5jb25zdCBzcGFjZXIgPSBcIlx1MDBBMFwiO1xuZnVuY3Rpb24gZmlsZXNpemUoYnl0ZXM6IG51bWJlcik6IHN0cmluZyB7XG5cdGNvbnN0IHNpZ24gPSBieXRlcyA8IDAgPyBcIi1cIiA6IFwiXCI7XG5cdGNvbnN0IG4gPSBNYXRoLmFicyhieXRlcyk7XG5cdGlmIChuIDwgMTAwMCkge1xuXHRcdHJldHVybiBgJHtzaWdufSR7bn0ke3NwYWNlcn1CYDtcblx0fVxuXHRpZiAobiA8IDEwMDAgKiAxMDAwKSB7XG5cdFx0cmV0dXJuIGAke3NpZ259JHsobiAvIDEwMDApLnRvRml4ZWQoMil9JHtzcGFjZXJ9S0JgO1xuXHR9XG5cdGlmIChuIDwgMTAwMCAqIDEwMDAgKiAxMDAwKSB7XG5cdFx0cmV0dXJuIGAke3NpZ259JHsobiAvIDEwMDAgLyAxMDAwKS50b0ZpeGVkKDIpfSR7c3BhY2VyfU1CYDtcblx0fVxuXHRpZiAobiA8IDEwMDAgKiAxMDAwICogMTAwMCAqIDEwMDApIHtcblx0XHRyZXR1cm4gYCR7c2lnbn0keyhuIC8gMTAwMCAvIDEwMDAgLyAxMDAwKS50b0ZpeGVkKDIpfSR7c3BhY2VyfUdCYDtcblx0fVxuXHR0aHJvdyBuZXcgRXJyb3IoXCJUb28gbGFyZ2UgZmlsZSBzaXplISEgQXJlIHlvdSBzdXJlP1wiKTtcbn1cblxuZnVuY3Rpb24gbWFya2Rvd25UYWJsZShcblx0ZGF0YTogQXJyYXk8Q29tcGFyZVJlc3VsdD4sXG5cdHJlZFRocmVzaG9sZDogbnVtYmVyLFxuKTogc3RyaW5nIHtcblx0Y29uc3Qgcm93cyA9IGRhdGFcblx0XHQubWFwKChkKSA9PiB7XG5cdFx0XHRyZXR1cm4gYCR7ZC5tZXRhZmlsZX0gfCAke2Qub3V0ZmlsZX0gfCAke3JlbmRlclNpemUoZCl9IHwgJHtyZW5kZXJOb3RlKFxuXHRcdFx0XHRkLFxuXHRcdFx0XHRyZWRUaHJlc2hvbGQsXG5cdFx0XHQpfVxcbmA7XG5cdFx0fSlcblx0XHQuam9pbihcIlwiKTtcblxuXHRyZXR1cm4gYFxuTWV0YSBGaWxlIHwgT3V0IEZpbGUgIHwgU2l6ZSAocmF3KSB8IE5vdGUgXG4tLS0tLS0tLS0tfC0tLS0tLS0tLS18LS0tLS0tLS0tLS06fC0tLS0tLVxuJHtyb3dzfWA7XG59XG5cbi8qKlxuICogRmluZCB0aGUgdG9wIE4gbGFyZ2VzdCBub2RlcyBpbiByb290IHRyZWUuXG4gKiBEaWcgbm9kZXMgdW50aWwgdGhlIGRlcHRoIG9mIDMuXG4gKi9cbmZ1bmN0aW9uIGZpbmRMYXJnZURpcmVjdG9yaWVzKHJvb3Q6IFRyZWVNYXBOb2RlLCBOOiBudW1iZXIpIHtcblx0Y29uc3Qgbm9kZXM6IFRyZWVNYXBOb2RlW10gPSBbXTtcblx0Y29uc3QgcXVldWU6IEFycmF5PHsgbm9kZTogVHJlZU1hcE5vZGU7IGRlcHRoOiBudW1iZXIgfT4gPSBbXG5cdFx0eyBub2RlOiByb290LCBkZXB0aDogMCB9LFxuXHRdO1xuXHR3aGlsZSAocXVldWUubGVuZ3RoID4gMCkge1xuXHRcdGNvbnN0IHNoaWZ0ID0gcXVldWUuc2hpZnQoKTtcblx0XHRpZiAoIXNoaWZ0KSB7XG5cdFx0XHRicmVhaztcblx0XHR9XG5cdFx0Y29uc3QgeyBub2RlLCBkZXB0aCB9ID0gc2hpZnQ7XG5cdFx0aWYgKGRlcHRoID09PSAzKSB7XG5cdFx0XHRub2Rlcy5wdXNoKG5vZGUpO1xuXHRcdFx0Y29udGludWU7XG5cdFx0fVxuXHRcdGlmIChub2RlLmNoaWxkcmVuLmxlbmd0aCA9PT0gMCkge1xuXHRcdFx0bm9kZXMucHVzaChub2RlKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0Zm9yIChjb25zdCBpdGVtIG9mIG5vZGUuY2hpbGRyZW4pIHtcblx0XHRcdFx0cXVldWUucHVzaCh7IG5vZGU6IGl0ZW0sIGRlcHRoOiBkZXB0aCArIDEgfSk7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cdGNvbnN0IGxhcmdlTm9kZXMgPSBub2Rlcy5zb3J0KChhLCBiKSA9PiBiLnZhbHVlIC0gYS52YWx1ZSkuc2xpY2UoMCwgTik7XG5cdHJldHVybiB7XG5cdFx0bGFyZ2VOb2Rlcyxcblx0XHRoYXNPdGhlcjogbm9kZXMubGVuZ3RoID4gTixcblx0fTtcbn1cblxuZnVuY3Rpb24gZml4ZWRQZXJjZW50KG46IG51bWJlciwgZDogbnVtYmVyKTogbnVtYmVyIHtcblx0cmV0dXJuIE51bWJlci5wYXJzZUZsb2F0KCgobiAvIGQpICogMTAwKS50b0ZpeGVkKDEpKTtcbn1cblxuZnVuY3Rpb24gZmlsZVNpemVUYWJsZShcblx0ZGF0YTogQXJyYXk8Q29tcGFyZVJlc3VsdD4sXG5cdHRvcE5MYXJnZXN0UGF0aHM6IG51bWJlcixcbik6IHN0cmluZyB7XG5cdGlmIChkYXRhLmxlbmd0aCA9PT0gMCB8fCB0b3BOTGFyZ2VzdFBhdGhzIDw9IDApIHtcblx0XHRyZXR1cm4gXCJcIjtcblx0fVxuXHRsZXQgb3V0cHV0ID0gXCJcIjtcblx0b3V0cHV0ICs9IFwiPGRldGFpbHM+XFxuXCI7XG5cdG91dHB1dCArPSBcIjxzdW1tYXJ5Pkxhcmdlc3QgcGF0aHM8L3N1bW1hcnk+XFxuXCI7XG5cdG91dHB1dCArPSBgVGhlc2UgdmlzdWFsaXphdGlvbiBzaG93cyB0b3AgJHt0b3BOTGFyZ2VzdFBhdGhzfSBsYXJnZXN0IHBhdGhzIGluIHRoZSBidW5kbGUuXFxuYDtcblx0Zm9yIChjb25zdCBkIG9mIGRhdGEpIHtcblx0XHRvdXRwdXQgKz0gXCJcXG5cIjtcblx0XHRvdXRwdXQgKz0gYCMjIE1ldGEgZmlsZTogJHtkLm1ldGFmaWxlfSwgT3V0IGZpbGU6ICR7ZC5vdXRmaWxlfVxcbmA7XG5cdFx0aWYgKCFkLnRyZWUpIHtcblx0XHRcdG91dHB1dCArPSBcIlx1RkUwRlx1RkUwRlx1RDgzRFx1REREMVx1RkUwRkRlbGV0ZWRcXG5cIjtcblx0XHRcdGNvbnRpbnVlO1xuXHRcdH1cblx0XHRvdXRwdXQgKz0gXCJ8IFBhdGggfCBTaXplIHxcXG5cIjtcblx0XHRvdXRwdXQgKz0gXCJ8LS0tLS0tfC0tLS0tLS18XFxuXCI7XG5cdFx0Y29uc3QgdG90YWxTaXplID0gZC50cmVlLnZhbHVlO1xuXHRcdGNvbnN0IHsgbGFyZ2VOb2RlcywgaGFzT3RoZXIgfSA9IGZpbmRMYXJnZURpcmVjdG9yaWVzKFxuXHRcdFx0ZC50cmVlLFxuXHRcdFx0dG9wTkxhcmdlc3RQYXRocyxcblx0XHQpO1xuXHRcdGZvciAoY29uc3QgeyBwYXRoLCB2YWx1ZSB9IG9mIGxhcmdlTm9kZXMpIHtcblx0XHRcdGNvbnN0IHBlcmNlbnQgPSBmaXhlZFBlcmNlbnQodmFsdWUsIHRvdGFsU2l6ZSk7XG5cdFx0XHRvdXRwdXQgKz0gYHwgJHtwYXRofSB8ICR7cmVuZGVyQmFyKHBlcmNlbnQsIHZhbHVlKX0gfFxcbmA7XG5cdFx0fVxuXHRcdGlmIChoYXNPdGhlcikge1xuXHRcdFx0Y29uc3Qgb3RoZXJTaXplID0gdG90YWxTaXplIC0gbGFyZ2VOb2Rlc1swXS52YWx1ZTtcblx0XHRcdGNvbnN0IG90aGVyUGVyY2VudCA9IGZpeGVkUGVyY2VudChvdGhlclNpemUsIHRvdGFsU2l6ZSk7XG5cdFx0XHRvdXRwdXQgKz0gYHwgKG90aGVyKSB8ICR7cmVuZGVyQmFyKG90aGVyUGVyY2VudCwgb3RoZXJTaXplKX0gfFxcbmA7XG5cdFx0fVxuXHR9XG5cdG91dHB1dCArPSBcIjwvZGV0YWlscz5cXG5cIjtcblx0cmV0dXJuIG91dHB1dDtcbn1cblxuZnVuY3Rpb24gcmVuZGVyQmFyKHBlcmNlbnQ6IG51bWJlciwgYnl0ZXM6IG51bWJlcik6IHN0cmluZyB7XG5cdGNvbnN0IGJhciA9IHByb2dyZXNzKHBlcmNlbnQgLyAxMDApO1xuXHRyZXR1cm4gYFxcJHt7XFxcXGNvbG9ye0dvbGRlbnJvZH17ICR7YmFyfSB9fX1cXCQgJHtwZXJjZW50LnRvRml4ZWQoXG5cdFx0MSxcblx0KX0lLCAke2ZpbGVzaXplKGJ5dGVzKX1gO1xufVxuXG4vLyBCbG9jayBwcm9ncmVzc2lvbiBpcyAxLzggPSAwLjEyNVxuY29uc3QgYmxvY2tzID0gW1wiXCIsIFwiXHUyNThGXCIsIFwiXHUyNThFXCIsIFwiXHUyNThEXCIsIFwiXHUyNThDXCIsIFwiXHUyNThCXCIsIFwiXHUyNThBXCIsIFwiXHUyNTg5XCIsIFwiXHUyNTg4XCJdO1xuY29uc3QgcHJvZ3Jlc3Npb24gPSAxIC8gKGJsb2Nrcy5sZW5ndGggLSAxKTtcbmZ1bmN0aW9uIHByb2dyZXNzKHZhbHVlOiBudW1iZXIsIGxlbmd0aCA9IDI1LCB2bWluID0gMC4wLCB2bWF4ID0gMS4wKSB7XG5cdGNvbnN0IHYgPSB2YWx1ZSAqIGxlbmd0aDtcblx0Y29uc3QgaW50ZWdlclBhcnQgPSBNYXRoLmZsb29yKHYpO1xuXHRjb25zdCBmcmFjdGlvbmFsUGFydCA9IHYgLSBpbnRlZ2VyUGFydDtcblx0Y29uc3QgaSA9IE1hdGgucm91bmQoXG5cdFx0KHByb2dyZXNzaW9uICogTWF0aC5mbG9vcihmcmFjdGlvbmFsUGFydCAvIHByb2dyZXNzaW9uKSkgLyBwcm9ncmVzc2lvbixcblx0KTtcblx0cmV0dXJuIFwiXHUyNTg4XCIucmVwZWF0KGludGVnZXJQYXJ0KSArIGJsb2Nrc1tpXTtcbn1cblxuZnVuY3Rpb24gcmVuZGVyU2l6ZShkOiBDb21wYXJlUmVzdWx0KTogc3RyaW5nIHtcblx0cmV0dXJuIGZpbGVzaXplKGQuYnl0ZXMpO1xufVxuXG5mdW5jdGlvbiByZW5kZXJOb3RlKGQ6IENvbXBhcmVSZXN1bHQsIHJlZFRocmVzaG9sZDogbnVtYmVyKTogc3RyaW5nIHtcblx0aWYgKGQucmVtYXJrID09PSBcImRlbGV0ZWRcIikge1xuXHRcdHJldHVybiBcIlx1RDgzRFx1REREMVx1RkUwRiBEZWxldGVkXCI7XG5cdH1cblx0aWYgKGQucmVtYXJrID09PSBcImFkZGVkXCIpIHtcblx0XHRyZXR1cm4gXCJcdUQ4M0NcdUREOTUgQWRkZWRcIjtcblx0fVxuXHRpZiAoZC5kaWZmKSB7XG5cdFx0Y29uc3QgcGVyY2VudENoYW5nZSA9IChkLmRpZmYgLyBkLmJ5dGVzKSAqIDEwMDtcblx0XHRyZXR1cm4gYCR7cmVuZGVyU3RhdHVzSW5kaWNhdG9yKHBlcmNlbnRDaGFuZ2UsIHJlZFRocmVzaG9sZCl9JHtmaWxlc2l6ZShcblx0XHRcdGQuZGlmZixcblx0XHQpfSAoJHtzaWduKHBlcmNlbnRDaGFuZ2UpfSR7cGVyY2VudENoYW5nZS50b0ZpeGVkKDEpfSUpYDtcblx0fVxuXHRyZXR1cm4gXCJcdTI3MDUgIE5vIGNoYW5nZVwiO1xufVxuXG5mdW5jdGlvbiBzaWduKG51bTogbnVtYmVyKTogc3RyaW5nIHtcblx0cmV0dXJuIG51bSA8IDAgPyBcIlwiIDogXCIrXCI7XG59XG5cbmZ1bmN0aW9uIHJlbmRlclN0YXR1c0luZGljYXRvcihcblx0cGVyY2VudENoYW5nZTogbnVtYmVyLFxuXHRyZWRUaHJlc2hvbGQ6IG51bWJlcixcbik6IHN0cmluZyB7XG5cdGxldCByZXM6IHN0cmluZztcblx0aWYgKHBlcmNlbnRDaGFuZ2UgPiAwICYmIHBlcmNlbnRDaGFuZ2UgPCByZWRUaHJlc2hvbGQpIHtcblx0XHRyZXMgPSBcIlx1MjZBMFx1RkUwRlwiO1xuXHR9IGVsc2UgaWYgKHBlcmNlbnRDaGFuZ2UgPj0gcmVkVGhyZXNob2xkKSB7XG5cdFx0cmVzID0gXCJcdTIwM0NcdUZFMEZcIjtcblx0fSBlbHNlIHtcblx0XHRyZXMgPSBcIlx1MjcwNSBcIjtcblx0fVxuXHRyZXR1cm4gYCR7cmVzfSAke3NpZ24ocGVyY2VudENoYW5nZSl9YDtcbn1cbiIsICJpbXBvcnQgZnMgZnJvbSBcIm5vZGU6ZnNcIjtcbmltcG9ydCBwYXRoIGZyb20gXCJub2RlOnBhdGhcIjtcbmltcG9ydCBwcm9jZXNzIGZyb20gXCJub2RlOnByb2Nlc3NcIjtcblxuaW1wb3J0ICogYXMgY29uc29sZSBmcm9tIFwibm9kZTpjb25zb2xlXCI7XG5pbXBvcnQgeyBnbG9iU3luYyB9IGZyb20gXCJnbG9iXCI7XG5pbXBvcnQgdHlwZSB7IElucHV0LCBSZXBvcnQgfSBmcm9tIFwiLi90eXBlc1wiO1xuaW1wb3J0IHsgbG9hZE1ldGFGaWxlIH0gZnJvbSBcIi4vdXRpbHNcIjtcblxuZXhwb3J0IGZ1bmN0aW9uIHJlcG9ydChpbnB1dDogSW5wdXQpOiB2b2lkIHtcblx0Y29uc3QgYWxsUGFnZVNpemVzID0gZ2V0QWxsUGFnZVNpemVzKGlucHV0KTtcblx0ZnMubWtkaXJTeW5jKHBhdGguam9pbihwcm9jZXNzLmN3ZCgpLCBpbnB1dC5hbmFseXplckRpcmVjdG9yeSksIHtcblx0XHRyZWN1cnNpdmU6IHRydWUsXG5cdH0pO1xuXHRjb25zdCByZXN1bHRKc29uUGF0aCA9IHBhdGguam9pbihcblx0XHRwcm9jZXNzLmN3ZCgpLFxuXHRcdGlucHV0LmFuYWx5emVyRGlyZWN0b3J5LFxuXHRcdFwiYnVuZGxlX2FuYWx5c2lzLmpzb25cIixcblx0KTtcblx0ZnMud3JpdGVGaWxlU3luYyhyZXN1bHRKc29uUGF0aCwgSlNPTi5zdHJpbmdpZnkoYWxsUGFnZVNpemVzLCBudWxsLCAyKSk7XG5cdGNvbnNvbGUubG9nKGBXcm90ZSAke3Jlc3VsdEpzb25QYXRofWApO1xufVxuXG5pbnRlcmZhY2UgTWV0YWZpbGVQYXRoIHtcblx0cmVhZG9ubHkgcmVsYXRpdmVQYXRoOiBzdHJpbmc7XG5cdHJlYWRvbmx5IGFic29sdXRlUGF0aDogc3RyaW5nO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZmluZE1ldGFmaWxlcyhpbnB1dDogSW5wdXQpOiBNZXRhZmlsZVBhdGhbXSB7XG5cdHJldHVybiBpbnB1dC5tZXRhZmlsZXMuZmxhdE1hcCgobWV0YWZpbGUpID0+IHtcblx0XHRyZXR1cm4gZ2xvYlN5bmMocGF0aC5qb2luKHByb2Nlc3MuY3dkKCksIG1ldGFmaWxlKSwge1xuXHRcdFx0bm9kaXI6IHRydWUsXG5cdFx0fSkubWFwKChtZXRhRmlsZVBhdGgpID0+IHtcblx0XHRcdHJldHVybiB7XG5cdFx0XHRcdHJlbGF0aXZlUGF0aDogcGF0aC5yZWxhdGl2ZShwcm9jZXNzLmN3ZCgpLCBtZXRhRmlsZVBhdGgpLFxuXHRcdFx0XHRhYnNvbHV0ZVBhdGg6IG1ldGFGaWxlUGF0aCxcblx0XHRcdH07XG5cdFx0fSk7XG5cdH0pO1xufVxuXG5mdW5jdGlvbiBnZXRBbGxQYWdlU2l6ZXMoaW5wdXQ6IElucHV0KTogUmVwb3J0IHtcblx0Y29uc3QgYWNjOiBSZXBvcnQgPSB7fTtcblx0cmV0dXJuIGZpbmRNZXRhZmlsZXMoaW5wdXQpLnJlZHVjZSgoYWNjLCB7IHJlbGF0aXZlUGF0aCwgYWJzb2x1dGVQYXRoIH0pID0+IHtcblx0XHR0cnkge1xuXHRcdFx0ZnMuYWNjZXNzU3luYyhhYnNvbHV0ZVBhdGgsIGZzLmNvbnN0YW50cy5SX09LKTtcblx0XHR9IGNhdGNoIChlcnIpIHtcblx0XHRcdGNvbnNvbGUuZXJyb3IoXG5cdFx0XHRcdGBObyBtZXRhIGZpbGUgZm91bmQgYXQgXCIke2Fic29sdXRlUGF0aH1cIiAtIGEgcGF0aCB0byBtZXRhIGZpbGUgbWF5IGJlIHdyb25nLCBvciBlc2J1aWxkIGlzIG5vdCBleGVjdXRlZC5gLFxuXHRcdFx0KTtcblx0XHRcdHByb2Nlc3MuZXhpdCgxKTtcblx0XHR9XG5cblx0XHRjb25zdCBtZXRhRmlsZUpzb24gPSBsb2FkTWV0YUZpbGUoYWJzb2x1dGVQYXRoKTtcblx0XHRPYmplY3QuZW50cmllcyhtZXRhRmlsZUpzb24ub3V0cHV0cykucmVkdWNlKChhY2MsIG91dHB1dCkgPT4ge1xuXHRcdFx0Y29uc3QgW291dGZpbGUsIGJ1aWxkTWV0YV0gPSBvdXRwdXQ7XG5cdFx0XHRpZiAoXG5cdFx0XHRcdCFpbnB1dC5pbmNsdWRlRXh0ZW5zaW9ucy5zb21lKChleHQpID0+XG5cdFx0XHRcdFx0b3V0ZmlsZS50b0xvd2VyQ2FzZSgpLmVuZHNXaXRoKGV4dCksXG5cdFx0XHRcdClcblx0XHRcdCkge1xuXHRcdFx0XHRyZXR1cm4gYWNjO1xuXHRcdFx0fVxuXHRcdFx0YWNjW2Ake3JlbGF0aXZlUGF0aH0gLT4gJHtvdXRmaWxlfWBdID0ge1xuXHRcdFx0XHRieXRlczogYnVpbGRNZXRhLmJ5dGVzLFxuXHRcdFx0XHRtZXRhZmlsZTogcmVsYXRpdmVQYXRoLFxuXHRcdFx0XHRvdXRmaWxlLFxuXHRcdFx0fTtcblx0XHRcdHJldHVybiBhY2M7XG5cdFx0fSwgYWNjKTtcblx0XHRyZXR1cm4gYWNjO1xuXHR9LCBhY2MpO1xufVxuIiwgImltcG9ydCBmcyBmcm9tIFwibm9kZTpmc1wiO1xuXG5pbXBvcnQgdHlwZSB7IE1ldGFmaWxlIH0gZnJvbSBcImVzYnVpbGRcIjtcbmltcG9ydCB0eXBlIHsgUmVwb3J0IH0gZnJvbSBcIi4vdHlwZXNcIjtcblxuZnVuY3Rpb24gbG9hZEpzb25GaWxlKHBhdGg6IHN0cmluZykge1xuXHRyZXR1cm4gSlNPTi5wYXJzZShmcy5yZWFkRmlsZVN5bmMocGF0aCkudG9TdHJpbmcoXCJ1dGYtOFwiKSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBsb2FkTWV0YUZpbGUocGF0aDogc3RyaW5nKTogTWV0YWZpbGUge1xuXHRyZXR1cm4gbG9hZEpzb25GaWxlKHBhdGgpIGFzIE1ldGFmaWxlO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gbG9hZEFuYWx5c2lzSnNvbihwYXRoOiBzdHJpbmcpOiBSZXBvcnQge1xuXHRyZXR1cm4gbG9hZEpzb25GaWxlKHBhdGgpIGFzIFJlcG9ydDtcbn1cblxuLy8gaHR0cHM6Ly9naXRodWIuY29tL2FjdGlvbnMvdG9vbGtpdC9ibG9iLzgxYTczYWJhOGJlZGQ1MzJmNmVkZGNjNDFlZDNhMGZhZDhiMWNmZWIvcGFja2FnZXMvY29yZS9zcmMvY29yZS50cyNMMTI2XG5leHBvcnQgZnVuY3Rpb24gZ2V0U2luZ2xlSW5wdXQobmFtZTogc3RyaW5nKTogc3RyaW5nIHtcblx0Y29uc3QgdmFsID0gcHJvY2Vzcy5lbnZbYElOUFVUXyR7bmFtZS50b1VwcGVyQ2FzZSgpfWBdIHx8IFwiXCI7XG5cdHJldHVybiB2YWwudHJpbSgpO1xufVxuIl0sCiAgIm1hcHBpbmdzIjogIjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLFNBQVMscUJBQXFCOzs7QUNBOUIsT0FBT0EsU0FBUTtBQUNmLE9BQU9DLFdBQVU7OztBQ0RqQixPQUFPQyxTQUFRO0FBQ2YsT0FBT0MsV0FBVTtBQUNqQixPQUFPQyxjQUFhO0FBRXBCLFlBQVlDLGNBQWE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUNKekIsT0FBTyxRQUFRO0FBS2YsU0FBUyxhQUFhQyxPQUFjO0FBQ25DLFNBQU8sS0FBSyxNQUFNLEdBQUcsYUFBYUEsS0FBSSxFQUFFLFNBQVMs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QUMsR0FBRztBQUFBLE1BQzlELEVBQUU7QUFBQSxJQUNILENBQUMsS0FBSyxLQUFLLGFBQWEsQ0FBQyxHQUFHLGNBQWMsUUFBUSxDQUFDLENBQUM7QUFBQSxFQUNyRDtBQUNBLFNBQU87QUFDUjtBQUVBLFNBQVMsS0FBSyxLQUFxQjtBQUNsQyxTQUFPLE1BQU0sSUFBSSxLQUFLO0FBQ3ZCO0FBRUEsU0FBUyxzQkFDUixlQUNBLGNBQ1M7QUFDVCxNQUFJO0FBQ0osTUFBSSxnQkFBZ0IsS0FBSyxnQkFBZ0IsY0FBYztBQUN0RCxVQUFNO0FBQUEsRUFDUCxXQUFXLGlCQUFpQixjQUFjO0FBQ3pDLFVBQU07QUFBQSxFQUNQLE9BQU87QUFDTixVQUFNO0FBQUEsRUFDUDtBQUNBLFNBQU8sR0FBRyxHQUFHLElBQUksS0FBSyxhQUFhLENBQUM7QUFDckM7OztBRHhWQSxTQUFTLFdBQWtCO0FBQzFCLFFBQU0sZUFBZSxlQUFlLFdBQVc7QUFDL0MsTUFBSSxDQUFDLGNBQWM7QUFDbEIsVUFBTSxJQUFJLE1BQU0sNEJBQTRCO0FBQUEsRUFDN0M7QUFDQSxRQUFNLE9BQU8sZUFBZSxNQUFNO0FBQ2xDLE1BQUksQ0FBQyxNQUFNO0FBQ1YsVUFBTSxJQUFJLE1BQU0sdUJBQXVCO0FBQUEsRUFDeEM7QUFDQSxTQUFPO0FBQUEsSUFDTix1QkFBdUIsT0FBTztBQUFBLE1BQzdCLGVBQWUseUJBQXlCLEtBQUs7QUFBQSxNQUM3QztBQUFBLElBQ0Q7QUFBQSxJQUNBLGFBQWEsQ0FBQyxRQUFRLFFBQVEsTUFBTSxFQUFFO0FBQUEsTUFDckMsZUFBZSxjQUFjLEtBQUs7QUFBQSxJQUNuQztBQUFBLElBQ0Esa0JBQWtCLE9BQU87QUFBQSxNQUN4QixlQUFlLHFCQUFxQixLQUFLO0FBQUEsTUFDekM7QUFBQSxJQUNEO0FBQUEsSUFDQSxvQkFDQyxlQUFlLG9CQUFvQixLQUFLLGlCQUN2QyxNQUFNLEdBQUc7QUFBQSxJQUNYO0FBQUEsSUFDQSxtQkFBbUIsZUFBZSxtQkFBbUIsS0FBSztBQUFBLElBQzFELFdBQVcsYUFBYSxNQUFNLEdBQUc7QUFBQSxFQUNsQztBQUNEO0FBRU8sU0FBUyxJQUFJLFFBQWUsU0FBUyxHQUFTO0FBQ3BELFNBQU8sS0FBSztBQUNaLFVBQVEsS0FBSztBQUNkO0FBRUEsSUFBSSxZQUFZLFFBQVEsY0FBYyxRQUFRLEtBQUssQ0FBQyxDQUFDLEVBQUUsTUFBTTtBQUM1RCxNQUFJO0FBQ0w7IiwKICAibmFtZXMiOiBbImZzIiwgInBhdGgiLCAiZnMiLCAicGF0aCIsICJwcm9jZXNzIiwgImNvbnNvbGUiLCAicGF0aCIsICJmcyIsICJwYXRoIiwgInByb2Nlc3MiLCAiYWNjIiwgImV4dCIsICJwYXRoIiwgImZzIiwgImlucHV0IiwgImNoaWxkIiwgInNpZ24iXQp9Cg==
diff --git a/package-lock.json b/package-lock.json
index 79ef479..ee689fd 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -8,6 +8,9 @@
       "name": "esbuild-bundle-analyzer",
       "version": "0.5.0",
       "license": "MIT",
+      "dependencies": {
+        "glob": "^10.3.12"
+      },
       "devDependencies": {
         "@biomejs/biome": "^1.7.2",
         "@types/node": "^20.12.7",
@@ -539,6 +542,22 @@
         "node": ">=12"
       }
     },
+    "node_modules/@isaacs/cliui": {
+      "version": "8.0.2",
+      "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
+      "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
+      "dependencies": {
+        "string-width": "^5.1.2",
+        "string-width-cjs": "npm:string-width@^4.2.0",
+        "strip-ansi": "^7.0.1",
+        "strip-ansi-cjs": "npm:strip-ansi@^6.0.1",
+        "wrap-ansi": "^8.1.0",
+        "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0"
+      },
+      "engines": {
+        "node": ">=12"
+      }
+    },
     "node_modules/@jest/schemas": {
       "version": "29.6.3",
       "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz",
@@ -557,6 +576,15 @@
       "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==",
       "dev": true
     },
+    "node_modules/@pkgjs/parseargs": {
+      "version": "0.11.0",
+      "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
+      "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==",
+      "optional": true,
+      "engines": {
+        "node": ">=14"
+      }
+    },
     "node_modules/@rollup/rollup-android-arm-eabi": {
       "version": "4.17.2",
       "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.17.2.tgz",
@@ -937,6 +965,17 @@
         "node": ">= 6.0.0"
       }
     },
+    "node_modules/ansi-regex": {
+      "version": "6.0.1",
+      "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
+      "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==",
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/ansi-regex?sponsor=1"
+      }
+    },
     "node_modules/ansi-styles": {
       "version": "5.2.0",
       "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
@@ -966,6 +1005,19 @@
       "optional": true,
       "peer": true
     },
+    "node_modules/balanced-match": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+      "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
+    },
+    "node_modules/brace-expansion": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+      "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+      "dependencies": {
+        "balanced-match": "^1.0.0"
+      }
+    },
     "node_modules/browser-process-hrtime": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz",
@@ -1013,6 +1065,22 @@
         "node": "*"
       }
     },
+    "node_modules/color-convert": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+      "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+      "dependencies": {
+        "color-name": "~1.1.4"
+      },
+      "engines": {
+        "node": ">=7.0.0"
+      }
+    },
+    "node_modules/color-name": {
+      "version": "1.1.4",
+      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+      "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
+    },
     "node_modules/combined-stream": {
       "version": "1.0.8",
       "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
@@ -1037,7 +1105,6 @@
       "version": "7.0.3",
       "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
       "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
-      "dev": true,
       "dependencies": {
         "path-key": "^3.1.0",
         "shebang-command": "^2.0.0",
@@ -1183,6 +1250,16 @@
         "node": ">=8"
       }
     },
+    "node_modules/eastasianwidth": {
+      "version": "0.2.0",
+      "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
+      "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA=="
+    },
+    "node_modules/emoji-regex": {
+      "version": "9.2.2",
+      "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
+      "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="
+    },
     "node_modules/esbuild": {
       "version": "0.20.2",
       "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.2.tgz",
@@ -1299,6 +1376,21 @@
       "optional": true,
       "peer": true
     },
+    "node_modules/foreground-child": {
+      "version": "3.1.1",
+      "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz",
+      "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==",
+      "dependencies": {
+        "cross-spawn": "^7.0.0",
+        "signal-exit": "^4.0.1"
+      },
+      "engines": {
+        "node": ">=14"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/isaacs"
+      }
+    },
     "node_modules/form-data": {
       "version": "3.0.1",
       "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz",
@@ -1338,6 +1430,27 @@
         "node": "*"
       }
     },
+    "node_modules/glob": {
+      "version": "10.3.12",
+      "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.12.tgz",
+      "integrity": "sha512-TCNv8vJ+xz4QiqTpfOJA7HvYv+tNIRHKfUWw/q+v2jdgN4ebz+KY9tGx5J4rHP0o84mNP+ApH66HRX8us3Khqg==",
+      "dependencies": {
+        "foreground-child": "^3.1.0",
+        "jackspeak": "^2.3.6",
+        "minimatch": "^9.0.1",
+        "minipass": "^7.0.4",
+        "path-scurry": "^1.10.2"
+      },
+      "bin": {
+        "glob": "dist/esm/bin.mjs"
+      },
+      "engines": {
+        "node": ">=16 || 14 >=14.17"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/isaacs"
+      }
+    },
     "node_modules/html-encoding-sniffer": {
       "version": "2.0.1",
       "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz",
@@ -1397,6 +1510,14 @@
         "node": ">=0.10.0"
       }
     },
+    "node_modules/is-fullwidth-code-point": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+      "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+      "engines": {
+        "node": ">=8"
+      }
+    },
     "node_modules/is-potential-custom-element-name": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz",
@@ -1408,8 +1529,24 @@
     "node_modules/isexe": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
-      "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
-      "dev": true
+      "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA="
+    },
+    "node_modules/jackspeak": {
+      "version": "2.3.6",
+      "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz",
+      "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==",
+      "dependencies": {
+        "@isaacs/cliui": "^8.0.2"
+      },
+      "engines": {
+        "node": ">=14"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/isaacs"
+      },
+      "optionalDependencies": {
+        "@pkgjs/parseargs": "^0.11.0"
+      }
     },
     "node_modules/jsdom": {
       "version": "16.6.0",
@@ -1507,6 +1644,14 @@
         "get-func-name": "^2.0.1"
       }
     },
+    "node_modules/lru-cache": {
+      "version": "10.2.2",
+      "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.2.tgz",
+      "integrity": "sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==",
+      "engines": {
+        "node": "14 || >=16.14"
+      }
+    },
     "node_modules/magic-string": {
       "version": "0.30.10",
       "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.10.tgz",
@@ -1547,6 +1692,28 @@
         "node": ">= 0.6"
       }
     },
+    "node_modules/minimatch": {
+      "version": "9.0.4",
+      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz",
+      "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==",
+      "dependencies": {
+        "brace-expansion": "^2.0.1"
+      },
+      "engines": {
+        "node": ">=16 || 14 >=14.17"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/isaacs"
+      }
+    },
+    "node_modules/minipass": {
+      "version": "7.1.0",
+      "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.0.tgz",
+      "integrity": "sha512-oGZRv2OT1lO2UF1zUcwdTb3wqUwI0kBGTgt/T7OdSj6M6N5m3o5uPf0AIW6lVxGGoiWUR7e2AwTE+xiwK8WQig==",
+      "engines": {
+        "node": ">=16 || 14 >=14.17"
+      }
+    },
     "node_modules/mlly": {
       "version": "1.6.1",
       "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.6.1.tgz",
@@ -1637,11 +1804,25 @@
       "version": "3.1.1",
       "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
       "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
-      "dev": true,
       "engines": {
         "node": ">=8"
       }
     },
+    "node_modules/path-scurry": {
+      "version": "1.10.2",
+      "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.2.tgz",
+      "integrity": "sha512-7xTavNy5RQXnsjANvVvMkEjvloOinkAjv/Z6Ildz9v2RinZ4SBKTWFOVRbaF8p0vpHnyjV/UwNDdKuUv6M5qcA==",
+      "dependencies": {
+        "lru-cache": "^10.2.0",
+        "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
+      },
+      "engines": {
+        "node": ">=16 || 14 >=14.17"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/isaacs"
+      }
+    },
     "node_modules/pathe": {
       "version": "1.1.2",
       "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz",
@@ -1829,7 +2010,6 @@
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
       "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
-      "dev": true,
       "dependencies": {
         "shebang-regex": "^3.0.0"
       },
@@ -1841,7 +2021,6 @@
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
       "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
-      "dev": true,
       "engines": {
         "node": ">=8"
       }
@@ -1852,6 +2031,17 @@
       "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==",
       "dev": true
     },
+    "node_modules/signal-exit": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
+      "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
+      "engines": {
+        "node": ">=14"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/isaacs"
+      }
+    },
     "node_modules/source-map": {
       "version": "0.6.1",
       "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
@@ -1884,6 +2074,94 @@
       "integrity": "sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==",
       "dev": true
     },
+    "node_modules/string-width": {
+      "version": "5.1.2",
+      "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
+      "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
+      "dependencies": {
+        "eastasianwidth": "^0.2.0",
+        "emoji-regex": "^9.2.2",
+        "strip-ansi": "^7.0.1"
+      },
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/string-width-cjs": {
+      "name": "string-width",
+      "version": "4.2.3",
+      "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+      "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+      "dependencies": {
+        "emoji-regex": "^8.0.0",
+        "is-fullwidth-code-point": "^3.0.0",
+        "strip-ansi": "^6.0.1"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/string-width-cjs/node_modules/ansi-regex": {
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+      "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/string-width-cjs/node_modules/emoji-regex": {
+      "version": "8.0.0",
+      "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+      "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
+    },
+    "node_modules/string-width-cjs/node_modules/strip-ansi": {
+      "version": "6.0.1",
+      "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+      "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+      "dependencies": {
+        "ansi-regex": "^5.0.1"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/strip-ansi": {
+      "version": "7.1.0",
+      "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
+      "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
+      "dependencies": {
+        "ansi-regex": "^6.0.1"
+      },
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/strip-ansi?sponsor=1"
+      }
+    },
+    "node_modules/strip-ansi-cjs": {
+      "name": "strip-ansi",
+      "version": "6.0.1",
+      "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+      "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+      "dependencies": {
+        "ansi-regex": "^5.0.1"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/strip-ansi-cjs/node_modules/ansi-regex": {
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+      "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+      "engines": {
+        "node": ">=8"
+      }
+    },
     "node_modules/strip-literal": {
       "version": "2.1.0",
       "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-2.1.0.tgz",
@@ -2297,18 +2575,6 @@
         "url": "https://github.com/sponsors/sindresorhus"
       }
     },
-    "node_modules/vitest/node_modules/signal-exit": {
-      "version": "4.1.0",
-      "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
-      "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
-      "dev": true,
-      "engines": {
-        "node": ">=14"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/isaacs"
-      }
-    },
     "node_modules/vitest/node_modules/strip-final-newline": {
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz",
@@ -2396,7 +2662,6 @@
       "version": "2.0.2",
       "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
       "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
-      "dev": true,
       "dependencies": {
         "isexe": "^2.0.0"
       },
@@ -2434,6 +2699,101 @@
         "node": ">=0.10.0"
       }
     },
+    "node_modules/wrap-ansi": {
+      "version": "8.1.0",
+      "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
+      "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
+      "dependencies": {
+        "ansi-styles": "^6.1.0",
+        "string-width": "^5.0.1",
+        "strip-ansi": "^7.0.1"
+      },
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+      }
+    },
+    "node_modules/wrap-ansi-cjs": {
+      "name": "wrap-ansi",
+      "version": "7.0.0",
+      "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+      "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+      "dependencies": {
+        "ansi-styles": "^4.0.0",
+        "string-width": "^4.1.0",
+        "strip-ansi": "^6.0.0"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+      }
+    },
+    "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": {
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+      "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": {
+      "version": "4.3.0",
+      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+      "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+      "dependencies": {
+        "color-convert": "^2.0.1"
+      },
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+      }
+    },
+    "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": {
+      "version": "8.0.0",
+      "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+      "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
+    },
+    "node_modules/wrap-ansi-cjs/node_modules/string-width": {
+      "version": "4.2.3",
+      "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+      "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+      "dependencies": {
+        "emoji-regex": "^8.0.0",
+        "is-fullwidth-code-point": "^3.0.0",
+        "strip-ansi": "^6.0.1"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": {
+      "version": "6.0.1",
+      "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+      "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+      "dependencies": {
+        "ansi-regex": "^5.0.1"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/wrap-ansi/node_modules/ansi-styles": {
+      "version": "6.2.1",
+      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
+      "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+      }
+    },
     "node_modules/ws": {
       "version": "7.5.3",
       "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.3.tgz",
@@ -2720,6 +3080,19 @@
       "dev": true,
       "optional": true
     },
+    "@isaacs/cliui": {
+      "version": "8.0.2",
+      "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
+      "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
+      "requires": {
+        "string-width": "^5.1.2",
+        "string-width-cjs": "npm:string-width@^4.2.0",
+        "strip-ansi": "^7.0.1",
+        "strip-ansi-cjs": "npm:strip-ansi@^6.0.1",
+        "wrap-ansi": "^8.1.0",
+        "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0"
+      }
+    },
     "@jest/schemas": {
       "version": "29.6.3",
       "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz",
@@ -2735,6 +3108,12 @@
       "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==",
       "dev": true
     },
+    "@pkgjs/parseargs": {
+      "version": "0.11.0",
+      "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
+      "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==",
+      "optional": true
+    },
     "@rollup/rollup-android-arm-eabi": {
       "version": "4.17.2",
       "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.17.2.tgz",
@@ -2985,6 +3364,11 @@
         "debug": "4"
       }
     },
+    "ansi-regex": {
+      "version": "6.0.1",
+      "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
+      "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA=="
+    },
     "ansi-styles": {
       "version": "5.2.0",
       "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
@@ -3005,6 +3389,19 @@
       "optional": true,
       "peer": true
     },
+    "balanced-match": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+      "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
+    },
+    "brace-expansion": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+      "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+      "requires": {
+        "balanced-match": "^1.0.0"
+      }
+    },
     "browser-process-hrtime": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz",
@@ -3043,6 +3440,19 @@
         "get-func-name": "^2.0.2"
       }
     },
+    "color-convert": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+      "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+      "requires": {
+        "color-name": "~1.1.4"
+      }
+    },
+    "color-name": {
+      "version": "1.1.4",
+      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+      "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
+    },
     "combined-stream": {
       "version": "1.0.8",
       "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
@@ -3064,7 +3474,6 @@
       "version": "7.0.3",
       "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
       "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
-      "dev": true,
       "requires": {
         "path-key": "^3.1.0",
         "shebang-command": "^2.0.0",
@@ -3182,6 +3591,16 @@
         }
       }
     },
+    "eastasianwidth": {
+      "version": "0.2.0",
+      "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
+      "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA=="
+    },
+    "emoji-regex": {
+      "version": "9.2.2",
+      "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
+      "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="
+    },
     "esbuild": {
       "version": "0.20.2",
       "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.2.tgz",
@@ -3269,6 +3688,15 @@
       "optional": true,
       "peer": true
     },
+    "foreground-child": {
+      "version": "3.1.1",
+      "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz",
+      "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==",
+      "requires": {
+        "cross-spawn": "^7.0.0",
+        "signal-exit": "^4.0.1"
+      }
+    },
     "form-data": {
       "version": "3.0.1",
       "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz",
@@ -3295,6 +3723,18 @@
       "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==",
       "dev": true
     },
+    "glob": {
+      "version": "10.3.12",
+      "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.12.tgz",
+      "integrity": "sha512-TCNv8vJ+xz4QiqTpfOJA7HvYv+tNIRHKfUWw/q+v2jdgN4ebz+KY9tGx5J4rHP0o84mNP+ApH66HRX8us3Khqg==",
+      "requires": {
+        "foreground-child": "^3.1.0",
+        "jackspeak": "^2.3.6",
+        "minimatch": "^9.0.1",
+        "minipass": "^7.0.4",
+        "path-scurry": "^1.10.2"
+      }
+    },
     "html-encoding-sniffer": {
       "version": "2.0.1",
       "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz",
@@ -3342,6 +3782,11 @@
         "safer-buffer": ">= 2.1.2 < 3"
       }
     },
+    "is-fullwidth-code-point": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+      "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="
+    },
     "is-potential-custom-element-name": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz",
@@ -3353,8 +3798,16 @@
     "isexe": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
-      "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
-      "dev": true
+      "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA="
+    },
+    "jackspeak": {
+      "version": "2.3.6",
+      "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz",
+      "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==",
+      "requires": {
+        "@isaacs/cliui": "^8.0.2",
+        "@pkgjs/parseargs": "^0.11.0"
+      }
     },
     "jsdom": {
       "version": "16.6.0",
@@ -3432,6 +3885,11 @@
         "get-func-name": "^2.0.1"
       }
     },
+    "lru-cache": {
+      "version": "10.2.2",
+      "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.2.tgz",
+      "integrity": "sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ=="
+    },
     "magic-string": {
       "version": "0.30.10",
       "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.10.tgz",
@@ -3466,6 +3924,19 @@
         "mime-db": "1.48.0"
       }
     },
+    "minimatch": {
+      "version": "9.0.4",
+      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz",
+      "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==",
+      "requires": {
+        "brace-expansion": "^2.0.1"
+      }
+    },
+    "minipass": {
+      "version": "7.1.0",
+      "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.0.tgz",
+      "integrity": "sha512-oGZRv2OT1lO2UF1zUcwdTb3wqUwI0kBGTgt/T7OdSj6M6N5m3o5uPf0AIW6lVxGGoiWUR7e2AwTE+xiwK8WQig=="
+    },
     "mlly": {
       "version": "1.6.1",
       "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.6.1.tgz",
@@ -3534,8 +4005,16 @@
     "path-key": {
       "version": "3.1.1",
       "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
-      "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
-      "dev": true
+      "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="
+    },
+    "path-scurry": {
+      "version": "1.10.2",
+      "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.2.tgz",
+      "integrity": "sha512-7xTavNy5RQXnsjANvVvMkEjvloOinkAjv/Z6Ildz9v2RinZ4SBKTWFOVRbaF8p0vpHnyjV/UwNDdKuUv6M5qcA==",
+      "requires": {
+        "lru-cache": "^10.2.0",
+        "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
+      }
     },
     "pathe": {
       "version": "1.1.2",
@@ -3683,7 +4162,6 @@
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
       "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
-      "dev": true,
       "requires": {
         "shebang-regex": "^3.0.0"
       }
@@ -3691,8 +4169,7 @@
     "shebang-regex": {
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
-      "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
-      "dev": true
+      "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="
     },
     "siginfo": {
       "version": "2.0.0",
@@ -3700,6 +4177,11 @@
       "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==",
       "dev": true
     },
+    "signal-exit": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
+      "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="
+    },
     "source-map": {
       "version": "0.6.1",
       "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
@@ -3726,6 +4208,69 @@
       "integrity": "sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==",
       "dev": true
     },
+    "string-width": {
+      "version": "5.1.2",
+      "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
+      "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
+      "requires": {
+        "eastasianwidth": "^0.2.0",
+        "emoji-regex": "^9.2.2",
+        "strip-ansi": "^7.0.1"
+      }
+    },
+    "string-width-cjs": {
+      "version": "npm:string-width@4.2.3",
+      "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+      "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+      "requires": {
+        "emoji-regex": "^8.0.0",
+        "is-fullwidth-code-point": "^3.0.0",
+        "strip-ansi": "^6.0.1"
+      },
+      "dependencies": {
+        "ansi-regex": {
+          "version": "5.0.1",
+          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+          "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="
+        },
+        "emoji-regex": {
+          "version": "8.0.0",
+          "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+          "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
+        },
+        "strip-ansi": {
+          "version": "6.0.1",
+          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+          "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+          "requires": {
+            "ansi-regex": "^5.0.1"
+          }
+        }
+      }
+    },
+    "strip-ansi": {
+      "version": "7.1.0",
+      "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
+      "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
+      "requires": {
+        "ansi-regex": "^6.0.1"
+      }
+    },
+    "strip-ansi-cjs": {
+      "version": "npm:strip-ansi@6.0.1",
+      "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+      "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+      "requires": {
+        "ansi-regex": "^5.0.1"
+      },
+      "dependencies": {
+        "ansi-regex": {
+          "version": "5.0.1",
+          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+          "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="
+        }
+      }
+    },
     "strip-literal": {
       "version": "2.1.0",
       "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-2.1.0.tgz",
@@ -3973,12 +4518,6 @@
           "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==",
           "dev": true
         },
-        "signal-exit": {
-          "version": "4.1.0",
-          "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
-          "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
-          "dev": true
-        },
         "strip-final-newline": {
           "version": "3.0.0",
           "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz",
@@ -4053,7 +4592,6 @@
       "version": "2.0.2",
       "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
       "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
-      "dev": true,
       "requires": {
         "isexe": "^2.0.0"
       }
@@ -4076,6 +4614,71 @@
       "optional": true,
       "peer": true
     },
+    "wrap-ansi": {
+      "version": "8.1.0",
+      "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
+      "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
+      "requires": {
+        "ansi-styles": "^6.1.0",
+        "string-width": "^5.0.1",
+        "strip-ansi": "^7.0.1"
+      },
+      "dependencies": {
+        "ansi-styles": {
+          "version": "6.2.1",
+          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
+          "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug=="
+        }
+      }
+    },
+    "wrap-ansi-cjs": {
+      "version": "npm:wrap-ansi@7.0.0",
+      "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+      "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+      "requires": {
+        "ansi-styles": "^4.0.0",
+        "string-width": "^4.1.0",
+        "strip-ansi": "^6.0.0"
+      },
+      "dependencies": {
+        "ansi-regex": {
+          "version": "5.0.1",
+          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+          "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="
+        },
+        "ansi-styles": {
+          "version": "4.3.0",
+          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+          "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+          "requires": {
+            "color-convert": "^2.0.1"
+          }
+        },
+        "emoji-regex": {
+          "version": "8.0.0",
+          "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+          "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
+        },
+        "string-width": {
+          "version": "4.2.3",
+          "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+          "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+          "requires": {
+            "emoji-regex": "^8.0.0",
+            "is-fullwidth-code-point": "^3.0.0",
+            "strip-ansi": "^6.0.1"
+          }
+        },
+        "strip-ansi": {
+          "version": "6.0.1",
+          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+          "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+          "requires": {
+            "ansi-regex": "^5.0.1"
+          }
+        }
+      }
+    },
     "ws": {
       "version": "7.5.3",
       "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.3.tgz",
diff --git a/package.json b/package.json
index b33b058..405ace8 100644
--- a/package.json
+++ b/package.json
@@ -28,6 +28,7 @@
   },
   "homepage": "https://github.com/exoego/esbuild-bundle-analysis#readme",
   "dependencies": {
+    "glob": "^10.3.12"
   },
   "devDependencies": {
     "@types/node": "^20.12.7",
diff --git a/src/compare.ts b/src/compare.ts
index f33684c..6ed57d2 100644
--- a/src/compare.ts
+++ b/src/compare.ts
@@ -1,5 +1,6 @@
 import fs from "node:fs";
 import path from "node:path";
+import { findMetafiles } from "./report";
 import type { CompareResult, Input, Report, TreeMapNode } from "./types";
 import { loadAnalysisJson, loadMetaFile } from "./utils";
 
@@ -160,11 +161,11 @@ function buildFileTree(input: Input) {
 		// Skip building tree if we don't need it.
 		return trees;
 	}
-	for (const metafile of input.metafiles) {
-		const metafileJson = loadMetaFile(path.join(process.cwd(), metafile));
+	for (const { relativePath, absolutePath } of findMetafiles(input)) {
+		const metafileJson = loadMetaFile(absolutePath);
 		for (const [outfile, buildMeta] of Object.entries(metafileJson.outputs)) {
 			const tree = buildRoot(buildMeta.inputs);
-			trees.set(treeKey(metafile, outfile), tree);
+			trees.set(treeKey(relativePath, outfile), tree);
 
 			fs.writeFileSync(
 				path.join(process.cwd(), input.analyzerDirectory, "tree.json"),
diff --git a/src/report.ts b/src/report.ts
index 158dcd3..a21fd66 100644
--- a/src/report.ts
+++ b/src/report.ts
@@ -2,6 +2,8 @@ import fs from "node:fs";
 import path from "node:path";
 import process from "node:process";
 
+import * as console from "node:console";
+import { globSync } from "glob";
 import type { Input, Report } from "./types";
 import { loadMetaFile } from "./utils";
 
@@ -19,20 +21,37 @@ export function report(input: Input): void {
 	console.log(`Wrote ${resultJsonPath}`);
 }
 
+interface MetafilePath {
+	readonly relativePath: string;
+	readonly absolutePath: string;
+}
+
+export function findMetafiles(input: Input): MetafilePath[] {
+	return input.metafiles.flatMap((metafile) => {
+		return globSync(path.join(process.cwd(), metafile), {
+			nodir: true,
+		}).map((metaFilePath) => {
+			return {
+				relativePath: path.relative(process.cwd(), metaFilePath),
+				absolutePath: metaFilePath,
+			};
+		});
+	});
+}
+
 function getAllPageSizes(input: Input): Report {
 	const acc: Report = {};
-	return input.metafiles.reduce((acc, metafile) => {
-		const metaFilePath = path.join(process.cwd(), metafile);
+	return findMetafiles(input).reduce((acc, { relativePath, absolutePath }) => {
 		try {
-			fs.accessSync(metaFilePath, fs.constants.R_OK);
+			fs.accessSync(absolutePath, fs.constants.R_OK);
 		} catch (err) {
 			console.error(
-				`No meta file found at "${metaFilePath}" - a path to meta file may be wrong, or esbuild is not executed.`,
+				`No meta file found at "${absolutePath}" - a path to meta file may be wrong, or esbuild is not executed.`,
 			);
 			process.exit(1);
 		}
 
-		const metaFileJson = loadMetaFile(metaFilePath);
+		const metaFileJson = loadMetaFile(absolutePath);
 		Object.entries(metaFileJson.outputs).reduce((acc, output) => {
 			const [outfile, buildMeta] = output;
 			if (
@@ -42,9 +61,9 @@ function getAllPageSizes(input: Input): Report {
 			) {
 				return acc;
 			}
-			acc[`${metafile} -> ${outfile}`] = {
+			acc[`${relativePath} -> ${outfile}`] = {
 				bytes: buildMeta.bytes,
-				metafile,
+				metafile: relativePath,
 				outfile,
 			};
 			return acc;