UNPKG

vitest

Version:

A blazing fast unit test framework powered by Vite

2,014 lines (1,651 loc) 708 kB
import { join, dirname, basename, relative, extname, resolve as resolve$2, normalize, isAbsolute, toNamespacedPath } from 'pathe'; import { E as EXIT_CODE_RESTART, c as configFiles, d as defaultPort } from './chunk-constants.bc18a549.js'; import { g as getCoverageProvider, C as CoverageProviderMap } from './chunk-integrations-coverage.e0a6acd2.js'; import { g as getEnvPackageName } from './chunk-env-node.affdd278.js'; import c from 'picocolors'; import { isPackageExists, resolveModule } from 'local-pkg'; import { c as isNode, d as relativePath, a as getCallLastIndex, e as removeUndefinedValues, f as isWindows } from './chunk-utils-env.04ffbef7.js'; import { isCI } from 'std-env'; import { loadConfigFromFile, createServer, mergeConfig } from 'vite'; import path$a from 'node:path'; import url, { fileURLToPath, pathToFileURL } from 'node:url'; import process$1 from 'node:process'; import fs$8, { promises, existsSync } from 'node:fs'; import k from 'path'; import require$$0 from 'os'; import require$$0$1, { promisify } from 'util'; import require$$0$2 from 'stream'; import require$$2 from 'events'; import require$$0$3, { existsSync as existsSync$1, readFileSync } from 'fs'; import { c as commonjsGlobal } from './vendor-_commonjsHelpers.addc3445.js'; import { slash as slash$2, normalizeRequestId, cleanUrl } from 'vite-node/utils'; import { ViteNodeRunner } from 'vite-node/client'; import { writeFile, rm } from 'node:fs/promises'; import { e as execa, s as signalExit } from './vendor-index.2cbcdd1e.js'; import { SourceMapConsumer } from 'source-map'; import K, { createRequire } from 'module'; import { parse as parse$4 } from 'acorn'; import { ancestor } from 'acorn-walk'; import { generateHash, calculateSuiteHash, someTasksAreOnly, interpretTaskModes, getTasks, getTests, hasFailed, getSuites } from '@vitest/runner/utils'; import require$$0$4 from 'child_process'; import { createDefer, shuffle, getSafeTimers, stringify as stringify$5, toArray as toArray$1 } from '@vitest/utils'; import { s as slash$1, t as toArray, g as groupBy, a as getEnvironmentTransformMode, n as notNullish, b as noop$1, d as deepMerge, c as stdout } from './chunk-utils-base.81f83dbd.js'; import { createHash } from 'crypto'; import { d as distDir, r as rootDir } from './chunk-paths.e36446b4.js'; import v8 from 'node:v8'; import { fork } from 'node:child_process'; import { c as createBirpc } from './vendor-index.783e7f3e.js'; import { MessageChannel } from 'node:worker_threads'; import { cpus, hostname } from 'node:os'; import Tinypool from 'tinypool'; import { performance } from 'perf_hooks'; import { g as getFullName, h as hasFailedSnapshot, a as parseErrorStacktrace, p as positionToOffset, l as lineSplitRE } from './chunk-utils-tasks.b41c8284.js'; import { unifiedDiff } from '@vitest/utils/diff'; import { ViteNodeServer } from 'vite-node/server'; import { d as decode, e as encode, M as MagicString } from './vendor-magic-string.es.b3bc5745.js'; import { builtinModules } from 'node:module'; import { createHash as createHash$1 } from 'node:crypto'; import { stripLiteral } from 'strip-literal'; import require$$0$5 from 'readline'; function _mergeNamespaces(n, m) { m.forEach(function (e) { e && typeof e !== 'string' && !Array.isArray(e) && Object.keys(e).forEach(function (k) { if (k !== 'default' && !(k in n)) { var d = Object.getOwnPropertyDescriptor(e, k); Object.defineProperty(n, k, d.get ? d : { enumerable: true, get: function () { return e[k]; } }); } }); }); return Object.freeze(n); } var version$1 = "0.29.4"; async function ensurePackageInstalled(dependency, root) { if (isPackageExists(dependency, { paths: [root] })) return true; const promptInstall = !isCI && process.stdout.isTTY; process.stderr.write(c.red(`${c.inverse(c.red(" MISSING DEP "))} Can not find dependency '${dependency}' `)); if (!promptInstall) return false; const prompts = await Promise.resolve().then(function () { return index; }); const { install } = await prompts.prompt({ type: "confirm", name: "install", message: c.reset(`Do you want to install ${c.green(dependency)}?`) }); if (install) { await (await import('./chunk-install-pkg.4121cd66.js')).installPackage(dependency, { dev: true }); process.stderr.write(c.yellow(` Package ${dependency} installed, re-run the command to start. `)); process.exit(EXIT_CODE_RESTART); return true; } return false; } /* How it works: `this.#head` is an instance of `Node` which keeps track of its current value and nests another instance of `Node` that keeps the value that comes after it. When a value is provided to `.enqueue()`, the code needs to iterate through `this.#head`, going deeper and deeper to find the last value. However, iterating through every single item is slow. This problem is solved by saving a reference to the last value as `this.#tail` so that it can reference it to add a new value. */ class Node { value; next; constructor(value) { this.value = value; } } class Queue { #head; #tail; #size; constructor() { this.clear(); } enqueue(value) { const node = new Node(value); if (this.#head) { this.#tail.next = node; this.#tail = node; } else { this.#head = node; this.#tail = node; } this.#size++; } dequeue() { const current = this.#head; if (!current) { return; } this.#head = this.#head.next; this.#size--; return current.value; } clear() { this.#head = undefined; this.#tail = undefined; this.#size = 0; } get size() { return this.#size; } * [Symbol.iterator]() { let current = this.#head; while (current) { yield current.value; current = current.next; } } } function pLimit(concurrency) { if (!((Number.isInteger(concurrency) || concurrency === Number.POSITIVE_INFINITY) && concurrency > 0)) { throw new TypeError('Expected `concurrency` to be a number from 1 and up'); } const queue = new Queue(); let activeCount = 0; const next = () => { activeCount--; if (queue.size > 0) { queue.dequeue()(); } }; const run = async (fn, resolve, args) => { activeCount++; const result = (async () => fn(...args))(); resolve(result); try { await result; } catch {} next(); }; const enqueue = (fn, resolve, args) => { queue.enqueue(run.bind(undefined, fn, resolve, args)); (async () => { // This function needs to wait until the next microtask before comparing // `activeCount` to `concurrency`, because `activeCount` is updated asynchronously // when the run function is dequeued and called. The comparison in the if-statement // needs to happen asynchronously as well to get an up-to-date value for `activeCount`. await Promise.resolve(); if (activeCount < concurrency && queue.size > 0) { queue.dequeue()(); } })(); }; const generator = (fn, ...args) => new Promise(resolve => { enqueue(fn, resolve, args); }); Object.defineProperties(generator, { activeCount: { get: () => activeCount, }, pendingCount: { get: () => queue.size, }, clearQueue: { value: () => { queue.clear(); }, }, }); return generator; } class EndError extends Error { constructor(value) { super(); this.value = value; } } // The input can also be a promise, so we await it. const testElement = async (element, tester) => tester(await element); // The input can also be a promise, so we `Promise.all()` them both. const finder = async element => { const values = await Promise.all(element); if (values[1] === true) { throw new EndError(values[0]); } return false; }; async function pLocate( iterable, tester, { concurrency = Number.POSITIVE_INFINITY, preserveOrder = true, } = {}, ) { const limit = pLimit(concurrency); // Start all the promises concurrently with optional limit. const items = [...iterable].map(element => [element, limit(testElement, element, tester)]); // Check the promises either serially or concurrently. const checkLimit = pLimit(preserveOrder ? 1 : Number.POSITIVE_INFINITY); try { await Promise.all(items.map(element => checkLimit(finder, element))); } catch (error) { if (error instanceof EndError) { return error.value; } throw error; } } const typeMappings = { directory: 'isDirectory', file: 'isFile', }; function checkType(type) { if (Object.hasOwnProperty.call(typeMappings, type)) { return; } throw new Error(`Invalid type specified: ${type}`); } const matchType = (type, stat) => stat[typeMappings[type]](); const toPath$1 = urlOrPath => urlOrPath instanceof URL ? fileURLToPath(urlOrPath) : urlOrPath; async function locatePath( paths, { cwd = process$1.cwd(), type = 'file', allowSymlinks = true, concurrency, preserveOrder, } = {}, ) { checkType(type); cwd = toPath$1(cwd); const statFunction = allowSymlinks ? promises.stat : promises.lstat; return pLocate(paths, async path_ => { try { const stat = await statFunction(path$a.resolve(cwd, path_)); return matchType(type, stat); } catch { return false; } }, {concurrency, preserveOrder}); } const toPath = urlOrPath => urlOrPath instanceof URL ? fileURLToPath(urlOrPath) : urlOrPath; const findUpStop = Symbol('findUpStop'); async function findUpMultiple(name, options = {}) { let directory = path$a.resolve(toPath(options.cwd) || ''); const {root} = path$a.parse(directory); const stopAt = path$a.resolve(directory, options.stopAt || root); const limit = options.limit || Number.POSITIVE_INFINITY; const paths = [name].flat(); const runMatcher = async locateOptions => { if (typeof name !== 'function') { return locatePath(paths, locateOptions); } const foundPath = await name(locateOptions.cwd); if (typeof foundPath === 'string') { return locatePath([foundPath], locateOptions); } return foundPath; }; const matches = []; // eslint-disable-next-line no-constant-condition while (true) { // eslint-disable-next-line no-await-in-loop const foundPath = await runMatcher({...options, cwd: directory}); if (foundPath === findUpStop) { break; } if (foundPath) { matches.push(path$a.resolve(directory, foundPath)); } if (directory === stopAt || matches.length >= limit) { break; } directory = path$a.dirname(directory); } return matches; } async function findUp(name, options = {}) { const matches = await findUpMultiple(name, {...options, limit: 1}); return matches[0]; } var tasks = {}; var utils$k = {}; var array$1 = {}; Object.defineProperty(array$1, "__esModule", { value: true }); array$1.splitWhen = array$1.flatten = void 0; function flatten(items) { return items.reduce((collection, item) => [].concat(collection, item), []); } array$1.flatten = flatten; function splitWhen(items, predicate) { const result = [[]]; let groupIndex = 0; for (const item of items) { if (predicate(item)) { groupIndex++; result[groupIndex] = []; } else { result[groupIndex].push(item); } } return result; } array$1.splitWhen = splitWhen; var errno$1 = {}; Object.defineProperty(errno$1, "__esModule", { value: true }); errno$1.isEnoentCodeError = void 0; function isEnoentCodeError(error) { return error.code === 'ENOENT'; } errno$1.isEnoentCodeError = isEnoentCodeError; var fs$7 = {}; Object.defineProperty(fs$7, "__esModule", { value: true }); fs$7.createDirentFromStats = void 0; class DirentFromStats$1 { constructor(name, stats) { this.name = name; this.isBlockDevice = stats.isBlockDevice.bind(stats); this.isCharacterDevice = stats.isCharacterDevice.bind(stats); this.isDirectory = stats.isDirectory.bind(stats); this.isFIFO = stats.isFIFO.bind(stats); this.isFile = stats.isFile.bind(stats); this.isSocket = stats.isSocket.bind(stats); this.isSymbolicLink = stats.isSymbolicLink.bind(stats); } } function createDirentFromStats$1(name, stats) { return new DirentFromStats$1(name, stats); } fs$7.createDirentFromStats = createDirentFromStats$1; var path$9 = {}; Object.defineProperty(path$9, "__esModule", { value: true }); path$9.removeLeadingDotSegment = path$9.escape = path$9.makeAbsolute = path$9.unixify = void 0; const path$8 = k; const LEADING_DOT_SEGMENT_CHARACTERS_COUNT = 2; // ./ or .\\ const UNESCAPED_GLOB_SYMBOLS_RE = /(\\?)([()*?[\]{|}]|^!|[!+@](?=\())/g; /** * Designed to work only with simple paths: `dir\\file`. */ function unixify(filepath) { return filepath.replace(/\\/g, '/'); } path$9.unixify = unixify; function makeAbsolute(cwd, filepath) { return path$8.resolve(cwd, filepath); } path$9.makeAbsolute = makeAbsolute; function escape(pattern) { return pattern.replace(UNESCAPED_GLOB_SYMBOLS_RE, '\\$2'); } path$9.escape = escape; function removeLeadingDotSegment(entry) { // We do not use `startsWith` because this is 10x slower than current implementation for some cases. // eslint-disable-next-line @typescript-eslint/prefer-string-starts-ends-with if (entry.charAt(0) === '.') { const secondCharactery = entry.charAt(1); if (secondCharactery === '/' || secondCharactery === '\\') { return entry.slice(LEADING_DOT_SEGMENT_CHARACTERS_COUNT); } } return entry; } path$9.removeLeadingDotSegment = removeLeadingDotSegment; var pattern$1 = {}; /*! * is-extglob <https://github.com/jonschlinkert/is-extglob> * * Copyright (c) 2014-2016, Jon Schlinkert. * Licensed under the MIT License. */ var isExtglob$1 = function isExtglob(str) { if (typeof str !== 'string' || str === '') { return false; } var match; while ((match = /(\\).|([@?!+*]\(.*\))/g.exec(str))) { if (match[2]) return true; str = str.slice(match.index + match[0].length); } return false; }; /*! * is-glob <https://github.com/jonschlinkert/is-glob> * * Copyright (c) 2014-2017, Jon Schlinkert. * Released under the MIT License. */ var isExtglob = isExtglob$1; var chars = { '{': '}', '(': ')', '[': ']'}; var strictCheck = function(str) { if (str[0] === '!') { return true; } var index = 0; var pipeIndex = -2; var closeSquareIndex = -2; var closeCurlyIndex = -2; var closeParenIndex = -2; var backSlashIndex = -2; while (index < str.length) { if (str[index] === '*') { return true; } if (str[index + 1] === '?' && /[\].+)]/.test(str[index])) { return true; } if (closeSquareIndex !== -1 && str[index] === '[' && str[index + 1] !== ']') { if (closeSquareIndex < index) { closeSquareIndex = str.indexOf(']', index); } if (closeSquareIndex > index) { if (backSlashIndex === -1 || backSlashIndex > closeSquareIndex) { return true; } backSlashIndex = str.indexOf('\\', index); if (backSlashIndex === -1 || backSlashIndex > closeSquareIndex) { return true; } } } if (closeCurlyIndex !== -1 && str[index] === '{' && str[index + 1] !== '}') { closeCurlyIndex = str.indexOf('}', index); if (closeCurlyIndex > index) { backSlashIndex = str.indexOf('\\', index); if (backSlashIndex === -1 || backSlashIndex > closeCurlyIndex) { return true; } } } if (closeParenIndex !== -1 && str[index] === '(' && str[index + 1] === '?' && /[:!=]/.test(str[index + 2]) && str[index + 3] !== ')') { closeParenIndex = str.indexOf(')', index); if (closeParenIndex > index) { backSlashIndex = str.indexOf('\\', index); if (backSlashIndex === -1 || backSlashIndex > closeParenIndex) { return true; } } } if (pipeIndex !== -1 && str[index] === '(' && str[index + 1] !== '|') { if (pipeIndex < index) { pipeIndex = str.indexOf('|', index); } if (pipeIndex !== -1 && str[pipeIndex + 1] !== ')') { closeParenIndex = str.indexOf(')', pipeIndex); if (closeParenIndex > pipeIndex) { backSlashIndex = str.indexOf('\\', pipeIndex); if (backSlashIndex === -1 || backSlashIndex > closeParenIndex) { return true; } } } } if (str[index] === '\\') { var open = str[index + 1]; index += 2; var close = chars[open]; if (close) { var n = str.indexOf(close, index); if (n !== -1) { index = n + 1; } } if (str[index] === '!') { return true; } } else { index++; } } return false; }; var relaxedCheck = function(str) { if (str[0] === '!') { return true; } var index = 0; while (index < str.length) { if (/[*?{}()[\]]/.test(str[index])) { return true; } if (str[index] === '\\') { var open = str[index + 1]; index += 2; var close = chars[open]; if (close) { var n = str.indexOf(close, index); if (n !== -1) { index = n + 1; } } if (str[index] === '!') { return true; } } else { index++; } } return false; }; var isGlob$1 = function isGlob(str, options) { if (typeof str !== 'string' || str === '') { return false; } if (isExtglob(str)) { return true; } var check = strictCheck; // optionally relax check if (options && options.strict === false) { check = relaxedCheck; } return check(str); }; var isGlob = isGlob$1; var pathPosixDirname = k.posix.dirname; var isWin32 = require$$0.platform() === 'win32'; var slash = '/'; var backslash = /\\/g; var enclosure = /[\{\[].*[\}\]]$/; var globby = /(^|[^\\])([\{\[]|\([^\)]+$)/; var escaped = /\\([\!\*\?\|\[\]\(\)\{\}])/g; /** * @param {string} str * @param {Object} opts * @param {boolean} [opts.flipBackslashes=true] * @returns {string} */ var globParent$1 = function globParent(str, opts) { var options = Object.assign({ flipBackslashes: true }, opts); // flip windows path separators if (options.flipBackslashes && isWin32 && str.indexOf(slash) < 0) { str = str.replace(backslash, slash); } // special case for strings ending in enclosure containing path separator if (enclosure.test(str)) { str += slash; } // preserves full path in case of trailing path separator str += 'a'; // remove path parts that are globby do { str = pathPosixDirname(str); } while (isGlob(str) || globby.test(str)); // remove escape chars and return result return str.replace(escaped, '$1'); }; var utils$j = {}; (function (exports) { exports.isInteger = num => { if (typeof num === 'number') { return Number.isInteger(num); } if (typeof num === 'string' && num.trim() !== '') { return Number.isInteger(Number(num)); } return false; }; /** * Find a node of the given type */ exports.find = (node, type) => node.nodes.find(node => node.type === type); /** * Find a node of the given type */ exports.exceedsLimit = (min, max, step = 1, limit) => { if (limit === false) return false; if (!exports.isInteger(min) || !exports.isInteger(max)) return false; return ((Number(max) - Number(min)) / Number(step)) >= limit; }; /** * Escape the given node with '\\' before node.value */ exports.escapeNode = (block, n = 0, type) => { let node = block.nodes[n]; if (!node) return; if ((type && node.type === type) || node.type === 'open' || node.type === 'close') { if (node.escaped !== true) { node.value = '\\' + node.value; node.escaped = true; } } }; /** * Returns true if the given brace node should be enclosed in literal braces */ exports.encloseBrace = node => { if (node.type !== 'brace') return false; if ((node.commas >> 0 + node.ranges >> 0) === 0) { node.invalid = true; return true; } return false; }; /** * Returns true if a brace node is invalid. */ exports.isInvalidBrace = block => { if (block.type !== 'brace') return false; if (block.invalid === true || block.dollar) return true; if ((block.commas >> 0 + block.ranges >> 0) === 0) { block.invalid = true; return true; } if (block.open !== true || block.close !== true) { block.invalid = true; return true; } return false; }; /** * Returns true if a node is an open or close node */ exports.isOpenOrClose = node => { if (node.type === 'open' || node.type === 'close') { return true; } return node.open === true || node.close === true; }; /** * Reduce an array of text nodes. */ exports.reduce = nodes => nodes.reduce((acc, node) => { if (node.type === 'text') acc.push(node.value); if (node.type === 'range') node.type = 'text'; return acc; }, []); /** * Flatten an array */ exports.flatten = (...args) => { const result = []; const flat = arr => { for (let i = 0; i < arr.length; i++) { let ele = arr[i]; Array.isArray(ele) ? flat(ele) : ele !== void 0 && result.push(ele); } return result; }; flat(args); return result; }; } (utils$j)); const utils$i = utils$j; var stringify$4 = (ast, options = {}) => { let stringify = (node, parent = {}) => { let invalidBlock = options.escapeInvalid && utils$i.isInvalidBrace(parent); let invalidNode = node.invalid === true && options.escapeInvalid === true; let output = ''; if (node.value) { if ((invalidBlock || invalidNode) && utils$i.isOpenOrClose(node)) { return '\\' + node.value; } return node.value; } if (node.value) { return node.value; } if (node.nodes) { for (let child of node.nodes) { output += stringify(child); } } return output; }; return stringify(ast); }; /*! * is-number <https://github.com/jonschlinkert/is-number> * * Copyright (c) 2014-present, Jon Schlinkert. * Released under the MIT License. */ var isNumber$2 = function(num) { if (typeof num === 'number') { return num - num === 0; } if (typeof num === 'string' && num.trim() !== '') { return Number.isFinite ? Number.isFinite(+num) : isFinite(+num); } return false; }; /*! * to-regex-range <https://github.com/micromatch/to-regex-range> * * Copyright (c) 2015-present, Jon Schlinkert. * Released under the MIT License. */ const isNumber$1 = isNumber$2; const toRegexRange$1 = (min, max, options) => { if (isNumber$1(min) === false) { throw new TypeError('toRegexRange: expected the first argument to be a number'); } if (max === void 0 || min === max) { return String(min); } if (isNumber$1(max) === false) { throw new TypeError('toRegexRange: expected the second argument to be a number.'); } let opts = { relaxZeros: true, ...options }; if (typeof opts.strictZeros === 'boolean') { opts.relaxZeros = opts.strictZeros === false; } let relax = String(opts.relaxZeros); let shorthand = String(opts.shorthand); let capture = String(opts.capture); let wrap = String(opts.wrap); let cacheKey = min + ':' + max + '=' + relax + shorthand + capture + wrap; if (toRegexRange$1.cache.hasOwnProperty(cacheKey)) { return toRegexRange$1.cache[cacheKey].result; } let a = Math.min(min, max); let b = Math.max(min, max); if (Math.abs(a - b) === 1) { let result = min + '|' + max; if (opts.capture) { return `(${result})`; } if (opts.wrap === false) { return result; } return `(?:${result})`; } let isPadded = hasPadding(min) || hasPadding(max); let state = { min, max, a, b }; let positives = []; let negatives = []; if (isPadded) { state.isPadded = isPadded; state.maxLen = String(state.max).length; } if (a < 0) { let newMin = b < 0 ? Math.abs(b) : 1; negatives = splitToPatterns(newMin, Math.abs(a), state, opts); a = state.a = 0; } if (b >= 0) { positives = splitToPatterns(a, b, state, opts); } state.negatives = negatives; state.positives = positives; state.result = collatePatterns(negatives, positives); if (opts.capture === true) { state.result = `(${state.result})`; } else if (opts.wrap !== false && (positives.length + negatives.length) > 1) { state.result = `(?:${state.result})`; } toRegexRange$1.cache[cacheKey] = state; return state.result; }; function collatePatterns(neg, pos, options) { let onlyNegative = filterPatterns(neg, pos, '-', false) || []; let onlyPositive = filterPatterns(pos, neg, '', false) || []; let intersected = filterPatterns(neg, pos, '-?', true) || []; let subpatterns = onlyNegative.concat(intersected).concat(onlyPositive); return subpatterns.join('|'); } function splitToRanges(min, max) { let nines = 1; let zeros = 1; let stop = countNines(min, nines); let stops = new Set([max]); while (min <= stop && stop <= max) { stops.add(stop); nines += 1; stop = countNines(min, nines); } stop = countZeros(max + 1, zeros) - 1; while (min < stop && stop <= max) { stops.add(stop); zeros += 1; stop = countZeros(max + 1, zeros) - 1; } stops = [...stops]; stops.sort(compare$1); return stops; } /** * Convert a range to a regex pattern * @param {Number} `start` * @param {Number} `stop` * @return {String} */ function rangeToPattern(start, stop, options) { if (start === stop) { return { pattern: start, count: [], digits: 0 }; } let zipped = zip(start, stop); let digits = zipped.length; let pattern = ''; let count = 0; for (let i = 0; i < digits; i++) { let [startDigit, stopDigit] = zipped[i]; if (startDigit === stopDigit) { pattern += startDigit; } else if (startDigit !== '0' || stopDigit !== '9') { pattern += toCharacterClass(startDigit, stopDigit); } else { count++; } } if (count) { pattern += options.shorthand === true ? '\\d' : '[0-9]'; } return { pattern, count: [count], digits }; } function splitToPatterns(min, max, tok, options) { let ranges = splitToRanges(min, max); let tokens = []; let start = min; let prev; for (let i = 0; i < ranges.length; i++) { let max = ranges[i]; let obj = rangeToPattern(String(start), String(max), options); let zeros = ''; if (!tok.isPadded && prev && prev.pattern === obj.pattern) { if (prev.count.length > 1) { prev.count.pop(); } prev.count.push(obj.count[0]); prev.string = prev.pattern + toQuantifier(prev.count); start = max + 1; continue; } if (tok.isPadded) { zeros = padZeros(max, tok, options); } obj.string = zeros + obj.pattern + toQuantifier(obj.count); tokens.push(obj); start = max + 1; prev = obj; } return tokens; } function filterPatterns(arr, comparison, prefix, intersection, options) { let result = []; for (let ele of arr) { let { string } = ele; // only push if _both_ are negative... if (!intersection && !contains(comparison, 'string', string)) { result.push(prefix + string); } // or _both_ are positive if (intersection && contains(comparison, 'string', string)) { result.push(prefix + string); } } return result; } /** * Zip strings */ function zip(a, b) { let arr = []; for (let i = 0; i < a.length; i++) arr.push([a[i], b[i]]); return arr; } function compare$1(a, b) { return a > b ? 1 : b > a ? -1 : 0; } function contains(arr, key, val) { return arr.some(ele => ele[key] === val); } function countNines(min, len) { return Number(String(min).slice(0, -len) + '9'.repeat(len)); } function countZeros(integer, zeros) { return integer - (integer % Math.pow(10, zeros)); } function toQuantifier(digits) { let [start = 0, stop = ''] = digits; if (stop || start > 1) { return `{${start + (stop ? ',' + stop : '')}}`; } return ''; } function toCharacterClass(a, b, options) { return `[${a}${(b - a === 1) ? '' : '-'}${b}]`; } function hasPadding(str) { return /^-?(0+)\d/.test(str); } function padZeros(value, tok, options) { if (!tok.isPadded) { return value; } let diff = Math.abs(tok.maxLen - String(value).length); let relax = options.relaxZeros !== false; switch (diff) { case 0: return ''; case 1: return relax ? '0?' : '0'; case 2: return relax ? '0{0,2}' : '00'; default: { return relax ? `0{0,${diff}}` : `0{${diff}}`; } } } /** * Cache */ toRegexRange$1.cache = {}; toRegexRange$1.clearCache = () => (toRegexRange$1.cache = {}); /** * Expose `toRegexRange` */ var toRegexRange_1 = toRegexRange$1; /*! * fill-range <https://github.com/jonschlinkert/fill-range> * * Copyright (c) 2014-present, Jon Schlinkert. * Licensed under the MIT License. */ const util$3 = require$$0$1; const toRegexRange = toRegexRange_1; const isObject$1 = val => val !== null && typeof val === 'object' && !Array.isArray(val); const transform$1 = toNumber => { return value => toNumber === true ? Number(value) : String(value); }; const isValidValue = value => { return typeof value === 'number' || (typeof value === 'string' && value !== ''); }; const isNumber = num => Number.isInteger(+num); const zeros = input => { let value = `${input}`; let index = -1; if (value[0] === '-') value = value.slice(1); if (value === '0') return false; while (value[++index] === '0'); return index > 0; }; const stringify$3 = (start, end, options) => { if (typeof start === 'string' || typeof end === 'string') { return true; } return options.stringify === true; }; const pad = (input, maxLength, toNumber) => { if (maxLength > 0) { let dash = input[0] === '-' ? '-' : ''; if (dash) input = input.slice(1); input = (dash + input.padStart(dash ? maxLength - 1 : maxLength, '0')); } if (toNumber === false) { return String(input); } return input; }; const toMaxLen = (input, maxLength) => { let negative = input[0] === '-' ? '-' : ''; if (negative) { input = input.slice(1); maxLength--; } while (input.length < maxLength) input = '0' + input; return negative ? ('-' + input) : input; }; const toSequence = (parts, options) => { parts.negatives.sort((a, b) => a < b ? -1 : a > b ? 1 : 0); parts.positives.sort((a, b) => a < b ? -1 : a > b ? 1 : 0); let prefix = options.capture ? '' : '?:'; let positives = ''; let negatives = ''; let result; if (parts.positives.length) { positives = parts.positives.join('|'); } if (parts.negatives.length) { negatives = `-(${prefix}${parts.negatives.join('|')})`; } if (positives && negatives) { result = `${positives}|${negatives}`; } else { result = positives || negatives; } if (options.wrap) { return `(${prefix}${result})`; } return result; }; const toRange = (a, b, isNumbers, options) => { if (isNumbers) { return toRegexRange(a, b, { wrap: false, ...options }); } let start = String.fromCharCode(a); if (a === b) return start; let stop = String.fromCharCode(b); return `[${start}-${stop}]`; }; const toRegex = (start, end, options) => { if (Array.isArray(start)) { let wrap = options.wrap === true; let prefix = options.capture ? '' : '?:'; return wrap ? `(${prefix}${start.join('|')})` : start.join('|'); } return toRegexRange(start, end, options); }; const rangeError = (...args) => { return new RangeError('Invalid range arguments: ' + util$3.inspect(...args)); }; const invalidRange = (start, end, options) => { if (options.strictRanges === true) throw rangeError([start, end]); return []; }; const invalidStep = (step, options) => { if (options.strictRanges === true) { throw new TypeError(`Expected step "${step}" to be a number`); } return []; }; const fillNumbers = (start, end, step = 1, options = {}) => { let a = Number(start); let b = Number(end); if (!Number.isInteger(a) || !Number.isInteger(b)) { if (options.strictRanges === true) throw rangeError([start, end]); return []; } // fix negative zero if (a === 0) a = 0; if (b === 0) b = 0; let descending = a > b; let startString = String(start); let endString = String(end); let stepString = String(step); step = Math.max(Math.abs(step), 1); let padded = zeros(startString) || zeros(endString) || zeros(stepString); let maxLen = padded ? Math.max(startString.length, endString.length, stepString.length) : 0; let toNumber = padded === false && stringify$3(start, end, options) === false; let format = options.transform || transform$1(toNumber); if (options.toRegex && step === 1) { return toRange(toMaxLen(start, maxLen), toMaxLen(end, maxLen), true, options); } let parts = { negatives: [], positives: [] }; let push = num => parts[num < 0 ? 'negatives' : 'positives'].push(Math.abs(num)); let range = []; let index = 0; while (descending ? a >= b : a <= b) { if (options.toRegex === true && step > 1) { push(a); } else { range.push(pad(format(a, index), maxLen, toNumber)); } a = descending ? a - step : a + step; index++; } if (options.toRegex === true) { return step > 1 ? toSequence(parts, options) : toRegex(range, null, { wrap: false, ...options }); } return range; }; const fillLetters = (start, end, step = 1, options = {}) => { if ((!isNumber(start) && start.length > 1) || (!isNumber(end) && end.length > 1)) { return invalidRange(start, end, options); } let format = options.transform || (val => String.fromCharCode(val)); let a = `${start}`.charCodeAt(0); let b = `${end}`.charCodeAt(0); let descending = a > b; let min = Math.min(a, b); let max = Math.max(a, b); if (options.toRegex && step === 1) { return toRange(min, max, false, options); } let range = []; let index = 0; while (descending ? a >= b : a <= b) { range.push(format(a, index)); a = descending ? a - step : a + step; index++; } if (options.toRegex === true) { return toRegex(range, null, { wrap: false, options }); } return range; }; const fill$2 = (start, end, step, options = {}) => { if (end == null && isValidValue(start)) { return [start]; } if (!isValidValue(start) || !isValidValue(end)) { return invalidRange(start, end, options); } if (typeof step === 'function') { return fill$2(start, end, 1, { transform: step }); } if (isObject$1(step)) { return fill$2(start, end, 0, step); } let opts = { ...options }; if (opts.capture === true) opts.wrap = true; step = step || opts.step || 1; if (!isNumber(step)) { if (step != null && !isObject$1(step)) return invalidStep(step, opts); return fill$2(start, end, 1, step); } if (isNumber(start) && isNumber(end)) { return fillNumbers(start, end, step, opts); } return fillLetters(start, end, Math.max(Math.abs(step), 1), opts); }; var fillRange = fill$2; const fill$1 = fillRange; const utils$h = utils$j; const compile$1 = (ast, options = {}) => { let walk = (node, parent = {}) => { let invalidBlock = utils$h.isInvalidBrace(parent); let invalidNode = node.invalid === true && options.escapeInvalid === true; let invalid = invalidBlock === true || invalidNode === true; let prefix = options.escapeInvalid === true ? '\\' : ''; let output = ''; if (node.isOpen === true) { return prefix + node.value; } if (node.isClose === true) { return prefix + node.value; } if (node.type === 'open') { return invalid ? (prefix + node.value) : '('; } if (node.type === 'close') { return invalid ? (prefix + node.value) : ')'; } if (node.type === 'comma') { return node.prev.type === 'comma' ? '' : (invalid ? node.value : '|'); } if (node.value) { return node.value; } if (node.nodes && node.ranges > 0) { let args = utils$h.reduce(node.nodes); let range = fill$1(...args, { ...options, wrap: false, toRegex: true }); if (range.length !== 0) { return args.length > 1 && range.length > 1 ? `(${range})` : range; } } if (node.nodes) { for (let child of node.nodes) { output += walk(child, node); } } return output; }; return walk(ast); }; var compile_1 = compile$1; const fill = fillRange; const stringify$2 = stringify$4; const utils$g = utils$j; const append = (queue = '', stash = '', enclose = false) => { let result = []; queue = [].concat(queue); stash = [].concat(stash); if (!stash.length) return queue; if (!queue.length) { return enclose ? utils$g.flatten(stash).map(ele => `{${ele}}`) : stash; } for (let item of queue) { if (Array.isArray(item)) { for (let value of item) { result.push(append(value, stash, enclose)); } } else { for (let ele of stash) { if (enclose === true && typeof ele === 'string') ele = `{${ele}}`; result.push(Array.isArray(ele) ? append(item, ele, enclose) : (item + ele)); } } } return utils$g.flatten(result); }; const expand$1 = (ast, options = {}) => { let rangeLimit = options.rangeLimit === void 0 ? 1000 : options.rangeLimit; let walk = (node, parent = {}) => { node.queue = []; let p = parent; let q = parent.queue; while (p.type !== 'brace' && p.type !== 'root' && p.parent) { p = p.parent; q = p.queue; } if (node.invalid || node.dollar) { q.push(append(q.pop(), stringify$2(node, options))); return; } if (node.type === 'brace' && node.invalid !== true && node.nodes.length === 2) { q.push(append(q.pop(), ['{}'])); return; } if (node.nodes && node.ranges > 0) { let args = utils$g.reduce(node.nodes); if (utils$g.exceedsLimit(...args, options.step, rangeLimit)) { throw new RangeError('expanded array length exceeds range limit. Use options.rangeLimit to increase or disable the limit.'); } let range = fill(...args, options); if (range.length === 0) { range = stringify$2(node, options); } q.push(append(q.pop(), range)); node.nodes = []; return; } let enclose = utils$g.encloseBrace(node); let queue = node.queue; let block = node; while (block.type !== 'brace' && block.type !== 'root' && block.parent) { block = block.parent; queue = block.queue; } for (let i = 0; i < node.nodes.length; i++) { let child = node.nodes[i]; if (child.type === 'comma' && node.type === 'brace') { if (i === 1) queue.push(''); queue.push(''); continue; } if (child.type === 'close') { q.push(append(q.pop(), queue, enclose)); continue; } if (child.value && child.type !== 'open') { queue.push(append(queue.pop(), child.value)); continue; } if (child.nodes) { walk(child, node); } } return queue; }; return utils$g.flatten(walk(ast)); }; var expand_1 = expand$1; var constants$4 = { MAX_LENGTH: 1024 * 64, // Digits CHAR_0: '0', /* 0 */ CHAR_9: '9', /* 9 */ // Alphabet chars. CHAR_UPPERCASE_A: 'A', /* A */ CHAR_LOWERCASE_A: 'a', /* a */ CHAR_UPPERCASE_Z: 'Z', /* Z */ CHAR_LOWERCASE_Z: 'z', /* z */ CHAR_LEFT_PARENTHESES: '(', /* ( */ CHAR_RIGHT_PARENTHESES: ')', /* ) */ CHAR_ASTERISK: '*', /* * */ // Non-alphabetic chars. CHAR_AMPERSAND: '&', /* & */ CHAR_AT: '@', /* @ */ CHAR_BACKSLASH: '\\', /* \ */ CHAR_BACKTICK: '`', /* ` */ CHAR_CARRIAGE_RETURN: '\r', /* \r */ CHAR_CIRCUMFLEX_ACCENT: '^', /* ^ */ CHAR_COLON: ':', /* : */ CHAR_COMMA: ',', /* , */ CHAR_DOLLAR: '$', /* . */ CHAR_DOT: '.', /* . */ CHAR_DOUBLE_QUOTE: '"', /* " */ CHAR_EQUAL: '=', /* = */ CHAR_EXCLAMATION_MARK: '!', /* ! */ CHAR_FORM_FEED: '\f', /* \f */ CHAR_FORWARD_SLASH: '/', /* / */ CHAR_HASH: '#', /* # */ CHAR_HYPHEN_MINUS: '-', /* - */ CHAR_LEFT_ANGLE_BRACKET: '<', /* < */ CHAR_LEFT_CURLY_BRACE: '{', /* { */ CHAR_LEFT_SQUARE_BRACKET: '[', /* [ */ CHAR_LINE_FEED: '\n', /* \n */ CHAR_NO_BREAK_SPACE: '\u00A0', /* \u00A0 */ CHAR_PERCENT: '%', /* % */ CHAR_PLUS: '+', /* + */ CHAR_QUESTION_MARK: '?', /* ? */ CHAR_RIGHT_ANGLE_BRACKET: '>', /* > */ CHAR_RIGHT_CURLY_BRACE: '}', /* } */ CHAR_RIGHT_SQUARE_BRACKET: ']', /* ] */ CHAR_SEMICOLON: ';', /* ; */ CHAR_SINGLE_QUOTE: '\'', /* ' */ CHAR_SPACE: ' ', /* */ CHAR_TAB: '\t', /* \t */ CHAR_UNDERSCORE: '_', /* _ */ CHAR_VERTICAL_LINE: '|', /* | */ CHAR_ZERO_WIDTH_NOBREAK_SPACE: '\uFEFF' /* \uFEFF */ }; const stringify$1 = stringify$4; /** * Constants */ const { MAX_LENGTH: MAX_LENGTH$1, CHAR_BACKSLASH, /* \ */ CHAR_BACKTICK, /* ` */ CHAR_COMMA: CHAR_COMMA$1, /* , */ CHAR_DOT: CHAR_DOT$1, /* . */ CHAR_LEFT_PARENTHESES: CHAR_LEFT_PARENTHESES$1, /* ( */ CHAR_RIGHT_PARENTHESES: CHAR_RIGHT_PARENTHESES$1, /* ) */ CHAR_LEFT_CURLY_BRACE: CHAR_LEFT_CURLY_BRACE$1, /* { */ CHAR_RIGHT_CURLY_BRACE: CHAR_RIGHT_CURLY_BRACE$1, /* } */ CHAR_LEFT_SQUARE_BRACKET: CHAR_LEFT_SQUARE_BRACKET$1, /* [ */ CHAR_RIGHT_SQUARE_BRACKET: CHAR_RIGHT_SQUARE_BRACKET$1, /* ] */ CHAR_DOUBLE_QUOTE, /* " */ CHAR_SINGLE_QUOTE, /* ' */ CHAR_NO_BREAK_SPACE, CHAR_ZERO_WIDTH_NOBREAK_SPACE } = constants$4; /** * parse */ const parse$3 = (input, options = {}) => { if (typeof input !== 'string') { throw new TypeError('Expected a string'); } let opts = options || {}; let max = typeof opts.maxLength === 'number' ? Math.min(MAX_LENGTH$1, opts.maxLength) : MAX_LENGTH$1; if (input.length > max) { throw new SyntaxError(`Input length (${input.length}), exceeds max characters (${max})`); } let ast = { type: 'root', input, nodes: [] }; let stack = [ast]; let block = ast; let prev = ast; let brackets = 0; let length = input.length; let index = 0; let depth = 0; let value; /** * Helpers */ const advance = () => input[index++]; const push = node => { if (node.type === 'text' && prev.type === 'dot') { prev.type = 'text'; } if (prev && prev.type === 'text' && node.type === 'text') { prev.value += node.value; return; } block.nodes.push(node); node.parent = block; node.prev = prev; prev = node; return node; }; push({ type: 'bos' }); while (index < length) { block = stack[stack.length - 1]; value = advance(); /** * Invalid chars */ if (value === CHAR_ZERO_WIDTH_NOBREAK_SPACE || value === CHAR_NO_BREAK_SPACE) { continue; } /** * Escaped chars */ if (value === CHAR_BACKSLASH) { push({ type: 'text', value: (options.keepEscaping ? value : '') + advance() }); continue; } /** * Right square bracket (literal): ']' */ if (value === CHAR_RIGHT_SQUARE_BRACKET$1) { push({ type: 'text', value: '\\' + value }); continue; } /** * Left square bracket: '[' */ if (value === CHAR_LEFT_SQUARE_BRACKET$1) { brackets++; let next; while (index < length && (next = advance())) { value += next; if (next === CHAR_LEFT_SQUARE_BRACKET$1) { brackets++; continue; } if (next === CHAR_BACKSLASH) { value += advance(); continue; } if (next === CHAR_RIGHT_SQUARE_BRACKET$1) { brackets--; if (brackets === 0) { break; } } } push({ type: 'text', value }); continue; } /** * Parentheses */ if (value === CHAR_LEFT_PARENTHESES$1) { block = push({ type: 'paren', nodes: [] }); stack.push(block); push({ type: 'text', value }); continue; } if (value === CHAR_RIGHT_PARENTHESES$1) { if (block.type !== 'paren') { push({ type: 'text', value }); continue; } block = stack.pop(); push({ type: 'text', value }); block = stack[stack.length - 1]; continue; } /** * Quotes: '|"|` */ if (value === CHAR_DOUBLE_QUOTE || value === CHAR_SINGLE_QUOTE || value === CHAR_BACKTICK) { let open = value; let next; if (options.keepQuotes !== true) { value = ''; } while (index < length && (next = advance())) { if (next === CHAR_BACKSLASH) { value += next + advance(); continue; } if (next === open) { if (options.keepQuotes === true) value += next; break; } value += next; } push({ type: 'text', value }); continue; } /** * Left curly brace: '{' */ if (value === CHAR_LEFT_CURLY_BRACE$1) { depth++; let dollar = prev.value && prev.value.slice(-1) === '$' || block.dollar === true; let brace = { type: 'brace', open: true, close: false, dollar, depth, commas: 0, ranges: 0, nodes: [] }; block = push(brace); stack.push(block); push({ type: 'open', value }); continue; } /** * Right curly brace: '}' */ if (value === CHAR_RIGHT_CURLY_BRACE$1) { if (block.type !== 'brace') { push({ type: 'text', value }); continue; } let type = 'close'; block = stack.pop(); block.close = true; push({ type, value }); depth--; block = stack[stack.length - 1]; continue; } /** * Comma: ',' */ if (value === CHAR_COMMA$1 && depth > 0) { if (block.ranges > 0) { block.ranges = 0; let open = block.nodes.shift(); block.nodes = [open, { type: 'text', value: stringify$1(block) }]; } push({ type: 'comma', value }); block.commas++; continue; } /** * Dot: '.' */ if (value === CHAR_DOT$1 && depth > 0 && block.commas === 0) { let siblings = block.nodes; if (depth === 0 || siblings.length === 0) { push({ type: 'text', value }); continue; } if (prev.type === 'dot') { block.range = []; prev.value += value; prev.type = 'range'; if (block.nodes.length !== 3 && block.nodes.length !== 5) { block.invalid = true; block.ranges = 0; prev.type = 'text'; continue; } block.ranges++; block.args = []; continue; } if (prev.type === 'range') { siblings.pop(); let before = siblings[siblings.length - 1]; before.value += prev.value + value; prev = before; block.ranges--; continue; } push({ type: 'dot', value }); continue; } /** * Text */ push({ type: 'text', value }); } // Mark imbalanced braces and brackets as invalid do { block = stack.pop(); if (block.type !== 'root') { block.nodes.forEach(node => { if (!node.nodes) { if (node.type === 'open') node.isOpen = true; if (node.type === 'close') node.isClose = true; if (!node.nodes) node.type = 'text'; node.invalid = true; } }); // get the location of the block on parent.nodes (block's siblings) let parent = stack[stack.length - 1]; let index = parent.nodes.indexOf(block); // replace the (invalid) block with it's nodes parent.nodes.splice(index, 1, ...block.nodes); } } while (stack.length > 0); push({ type: 'eos' }); return ast; }; var parse_1$1 = parse$3; const stringify = stringify$4; const compile = compile_1; const expand = expand_1; const parse$2 = parse_1$1; /** * Expand the given pattern or create a regex-compatible string. * * ```js * const braces = require('braces'); * console.log(braces('{a,b,c}', { compile: true })); //=> ['(a|b|c)'] * console.log(braces('{a,b,c}')); //=> ['a', 'b', 'c'] * ``` * @param {String} `str` * @param {Object} `options` * @return {String} * @api public */ const braces$1 = (input, options = {}) => { let output = []; if (Array.isArray(input)) { for (let pattern of input) { let result = braces$1.create(pattern, options); if (Array.isArray(result)) { output.push(...result); } else { output.push(result); } } } else { output = [].concat(braces$1.create(input, options)); } if (options && options.expand === true && options.nodupes === true) { output = [...new Set(output)]; } return output; }; /** * Parse the given `str` with the given `options`. * * ```js * // braces.parse(pattern, [, options]); * const ast = braces.parse('a/{b,c}/d'); * console.log(ast); * ``` * @param {String} pattern Brace pattern to parse * @param {Object} options * @return {Object} Returns an AST * @api public */ braces$1.parse = (input, options = {}) => parse$2(input, options); /** * Creates a braces string from an AST, or an AST node. * * ```js * const braces = require('braces'); * let ast = braces.parse('foo/{a,b}/bar'); * console.log(stringify(ast.nodes[2])); //=> '{a,b}' * ``` * @param {String} `input` Brace pattern or AST. * @param {Object} `options` * @return {Array} Returns an array of expanded values. * @api public */ braces$1.stringify = (input, options = {}) => { if (typeof input === 'string') { return stringify(braces$1.parse(input, options), options); } return stringify(input, options); }; /** * Compiles a brace pattern into a regex-compatible, optimized string. * This method is called by the main [braces](#braces) function by default. * * ```js * const braces = require('braces'); * console.log(braces.compile('a/{b,c