4516 lines
119 KiB
JavaScript
4516 lines
119 KiB
JavaScript
'use strict';
|
|
|
|
var path$3 = require('node:path');
|
|
var node_url = require('node:url');
|
|
var fs$1 = require('node:fs');
|
|
var esbuild = require('esbuild');
|
|
var rollup = require('rollup');
|
|
var os$1 = require('node:os');
|
|
var node_module = require('node:module');
|
|
var require$$0 = require('tty');
|
|
var require$$1 = require('util');
|
|
var require$$0$1 = require('path');
|
|
var require$$0$2 = require('crypto');
|
|
var fs$2 = require('fs');
|
|
var readline = require('node:readline');
|
|
var require$$2 = require('os');
|
|
|
|
const { version: version$2 } = JSON.parse(fs$1.readFileSync(new URL('../../package.json', (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (document.currentScript && document.currentScript.src || new URL('node-cjs/publicUtils.cjs', document.baseURI).href)))).toString());
|
|
const VERSION = version$2;
|
|
/**
|
|
* Prefix for resolved fs paths, since windows paths may not be valid as URLs.
|
|
*/
|
|
const FS_PREFIX = `/@fs/`;
|
|
const VITE_PACKAGE_DIR = path$3.resolve(
|
|
// import.meta.url is `dist/node/constants.js` after bundle
|
|
node_url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (document.currentScript && document.currentScript.src || new URL('node-cjs/publicUtils.cjs', document.baseURI).href))), '../../..');
|
|
const CLIENT_ENTRY = path$3.resolve(VITE_PACKAGE_DIR, 'dist/client/client.mjs');
|
|
path$3.resolve(VITE_PACKAGE_DIR, 'dist/client/env.mjs');
|
|
path$3.dirname(CLIENT_ENTRY);
|
|
|
|
const chars$1 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
|
|
const intToChar$1 = new Uint8Array(64); // 64 possible chars.
|
|
const charToInt$1 = new Uint8Array(128); // z is 122 in ASCII
|
|
for (let i = 0; i < chars$1.length; i++) {
|
|
const c = chars$1.charCodeAt(i);
|
|
intToChar$1[i] = c;
|
|
charToInt$1[c] = i;
|
|
}
|
|
|
|
// Matches the scheme of a URL, eg "http://"
|
|
var UrlType;
|
|
(function (UrlType) {
|
|
UrlType[UrlType["Empty"] = 1] = "Empty";
|
|
UrlType[UrlType["Hash"] = 2] = "Hash";
|
|
UrlType[UrlType["Query"] = 3] = "Query";
|
|
UrlType[UrlType["RelativePath"] = 4] = "RelativePath";
|
|
UrlType[UrlType["AbsolutePath"] = 5] = "AbsolutePath";
|
|
UrlType[UrlType["SchemeRelative"] = 6] = "SchemeRelative";
|
|
UrlType[UrlType["Absolute"] = 7] = "Absolute";
|
|
})(UrlType || (UrlType = {}));
|
|
|
|
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
|
|
const intToChar = new Uint8Array(64); // 64 possible chars.
|
|
const charToInt = new Uint8Array(128); // z is 122 in ASCII
|
|
for (let i = 0; i < chars.length; i++) {
|
|
const c = chars.charCodeAt(i);
|
|
intToChar[i] = c;
|
|
charToInt[c] = i;
|
|
}
|
|
|
|
function getDefaultExportFromCjs (x) {
|
|
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
|
|
}
|
|
|
|
var picocolors = {exports: {}};
|
|
|
|
let tty = require$$0;
|
|
|
|
let isColorSupported =
|
|
!("NO_COLOR" in process.env || process.argv.includes("--no-color")) &&
|
|
("FORCE_COLOR" in process.env ||
|
|
process.argv.includes("--color") ||
|
|
process.platform === "win32" ||
|
|
(tty.isatty(1) && process.env.TERM !== "dumb") ||
|
|
"CI" in process.env);
|
|
|
|
let formatter =
|
|
(open, close, replace = open) =>
|
|
input => {
|
|
let string = "" + input;
|
|
let index = string.indexOf(close, open.length);
|
|
return ~index
|
|
? open + replaceClose(string, close, replace, index) + close
|
|
: open + string + close
|
|
};
|
|
|
|
let replaceClose = (string, close, replace, index) => {
|
|
let start = string.substring(0, index) + replace;
|
|
let end = string.substring(index + close.length);
|
|
let nextIndex = end.indexOf(close);
|
|
return ~nextIndex ? start + replaceClose(end, close, replace, nextIndex) : start + end
|
|
};
|
|
|
|
let createColors = (enabled = isColorSupported) => ({
|
|
isColorSupported: enabled,
|
|
reset: enabled ? s => `\x1b[0m${s}\x1b[0m` : String,
|
|
bold: enabled ? formatter("\x1b[1m", "\x1b[22m", "\x1b[22m\x1b[1m") : String,
|
|
dim: enabled ? formatter("\x1b[2m", "\x1b[22m", "\x1b[22m\x1b[2m") : String,
|
|
italic: enabled ? formatter("\x1b[3m", "\x1b[23m") : String,
|
|
underline: enabled ? formatter("\x1b[4m", "\x1b[24m") : String,
|
|
inverse: enabled ? formatter("\x1b[7m", "\x1b[27m") : String,
|
|
hidden: enabled ? formatter("\x1b[8m", "\x1b[28m") : String,
|
|
strikethrough: enabled ? formatter("\x1b[9m", "\x1b[29m") : String,
|
|
black: enabled ? formatter("\x1b[30m", "\x1b[39m") : String,
|
|
red: enabled ? formatter("\x1b[31m", "\x1b[39m") : String,
|
|
green: enabled ? formatter("\x1b[32m", "\x1b[39m") : String,
|
|
yellow: enabled ? formatter("\x1b[33m", "\x1b[39m") : String,
|
|
blue: enabled ? formatter("\x1b[34m", "\x1b[39m") : String,
|
|
magenta: enabled ? formatter("\x1b[35m", "\x1b[39m") : String,
|
|
cyan: enabled ? formatter("\x1b[36m", "\x1b[39m") : String,
|
|
white: enabled ? formatter("\x1b[37m", "\x1b[39m") : String,
|
|
gray: enabled ? formatter("\x1b[90m", "\x1b[39m") : String,
|
|
bgBlack: enabled ? formatter("\x1b[40m", "\x1b[49m") : String,
|
|
bgRed: enabled ? formatter("\x1b[41m", "\x1b[49m") : String,
|
|
bgGreen: enabled ? formatter("\x1b[42m", "\x1b[49m") : String,
|
|
bgYellow: enabled ? formatter("\x1b[43m", "\x1b[49m") : String,
|
|
bgBlue: enabled ? formatter("\x1b[44m", "\x1b[49m") : String,
|
|
bgMagenta: enabled ? formatter("\x1b[45m", "\x1b[49m") : String,
|
|
bgCyan: enabled ? formatter("\x1b[46m", "\x1b[49m") : String,
|
|
bgWhite: enabled ? formatter("\x1b[47m", "\x1b[49m") : String,
|
|
});
|
|
|
|
picocolors.exports = createColors();
|
|
picocolors.exports.createColors = createColors;
|
|
|
|
var picocolorsExports = picocolors.exports;
|
|
var colors = /*@__PURE__*/getDefaultExportFromCjs(picocolorsExports);
|
|
|
|
var src = {exports: {}};
|
|
|
|
var browser$1 = {exports: {}};
|
|
|
|
/**
|
|
* Helpers.
|
|
*/
|
|
|
|
var ms;
|
|
var hasRequiredMs;
|
|
|
|
function requireMs () {
|
|
if (hasRequiredMs) return ms;
|
|
hasRequiredMs = 1;
|
|
var s = 1000;
|
|
var m = s * 60;
|
|
var h = m * 60;
|
|
var d = h * 24;
|
|
var w = d * 7;
|
|
var y = d * 365.25;
|
|
|
|
/**
|
|
* Parse or format the given `val`.
|
|
*
|
|
* Options:
|
|
*
|
|
* - `long` verbose formatting [false]
|
|
*
|
|
* @param {String|Number} val
|
|
* @param {Object} [options]
|
|
* @throws {Error} throw an error if val is not a non-empty string or a number
|
|
* @return {String|Number}
|
|
* @api public
|
|
*/
|
|
|
|
ms = function(val, options) {
|
|
options = options || {};
|
|
var type = typeof val;
|
|
if (type === 'string' && val.length > 0) {
|
|
return parse(val);
|
|
} else if (type === 'number' && isFinite(val)) {
|
|
return options.long ? fmtLong(val) : fmtShort(val);
|
|
}
|
|
throw new Error(
|
|
'val is not a non-empty string or a valid number. val=' +
|
|
JSON.stringify(val)
|
|
);
|
|
};
|
|
|
|
/**
|
|
* Parse the given `str` and return milliseconds.
|
|
*
|
|
* @param {String} str
|
|
* @return {Number}
|
|
* @api private
|
|
*/
|
|
|
|
function parse(str) {
|
|
str = String(str);
|
|
if (str.length > 100) {
|
|
return;
|
|
}
|
|
var match = /^(-?(?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec(
|
|
str
|
|
);
|
|
if (!match) {
|
|
return;
|
|
}
|
|
var n = parseFloat(match[1]);
|
|
var type = (match[2] || 'ms').toLowerCase();
|
|
switch (type) {
|
|
case 'years':
|
|
case 'year':
|
|
case 'yrs':
|
|
case 'yr':
|
|
case 'y':
|
|
return n * y;
|
|
case 'weeks':
|
|
case 'week':
|
|
case 'w':
|
|
return n * w;
|
|
case 'days':
|
|
case 'day':
|
|
case 'd':
|
|
return n * d;
|
|
case 'hours':
|
|
case 'hour':
|
|
case 'hrs':
|
|
case 'hr':
|
|
case 'h':
|
|
return n * h;
|
|
case 'minutes':
|
|
case 'minute':
|
|
case 'mins':
|
|
case 'min':
|
|
case 'm':
|
|
return n * m;
|
|
case 'seconds':
|
|
case 'second':
|
|
case 'secs':
|
|
case 'sec':
|
|
case 's':
|
|
return n * s;
|
|
case 'milliseconds':
|
|
case 'millisecond':
|
|
case 'msecs':
|
|
case 'msec':
|
|
case 'ms':
|
|
return n;
|
|
default:
|
|
return undefined;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Short format for `ms`.
|
|
*
|
|
* @param {Number} ms
|
|
* @return {String}
|
|
* @api private
|
|
*/
|
|
|
|
function fmtShort(ms) {
|
|
var msAbs = Math.abs(ms);
|
|
if (msAbs >= d) {
|
|
return Math.round(ms / d) + 'd';
|
|
}
|
|
if (msAbs >= h) {
|
|
return Math.round(ms / h) + 'h';
|
|
}
|
|
if (msAbs >= m) {
|
|
return Math.round(ms / m) + 'm';
|
|
}
|
|
if (msAbs >= s) {
|
|
return Math.round(ms / s) + 's';
|
|
}
|
|
return ms + 'ms';
|
|
}
|
|
|
|
/**
|
|
* Long format for `ms`.
|
|
*
|
|
* @param {Number} ms
|
|
* @return {String}
|
|
* @api private
|
|
*/
|
|
|
|
function fmtLong(ms) {
|
|
var msAbs = Math.abs(ms);
|
|
if (msAbs >= d) {
|
|
return plural(ms, msAbs, d, 'day');
|
|
}
|
|
if (msAbs >= h) {
|
|
return plural(ms, msAbs, h, 'hour');
|
|
}
|
|
if (msAbs >= m) {
|
|
return plural(ms, msAbs, m, 'minute');
|
|
}
|
|
if (msAbs >= s) {
|
|
return plural(ms, msAbs, s, 'second');
|
|
}
|
|
return ms + ' ms';
|
|
}
|
|
|
|
/**
|
|
* Pluralization helper.
|
|
*/
|
|
|
|
function plural(ms, msAbs, n, name) {
|
|
var isPlural = msAbs >= n * 1.5;
|
|
return Math.round(ms / n) + ' ' + name + (isPlural ? 's' : '');
|
|
}
|
|
return ms;
|
|
}
|
|
|
|
var common;
|
|
var hasRequiredCommon;
|
|
|
|
function requireCommon () {
|
|
if (hasRequiredCommon) return common;
|
|
hasRequiredCommon = 1;
|
|
/**
|
|
* This is the common logic for both the Node.js and web browser
|
|
* implementations of `debug()`.
|
|
*/
|
|
|
|
function setup(env) {
|
|
createDebug.debug = createDebug;
|
|
createDebug.default = createDebug;
|
|
createDebug.coerce = coerce;
|
|
createDebug.disable = disable;
|
|
createDebug.enable = enable;
|
|
createDebug.enabled = enabled;
|
|
createDebug.humanize = requireMs();
|
|
createDebug.destroy = destroy;
|
|
|
|
Object.keys(env).forEach(key => {
|
|
createDebug[key] = env[key];
|
|
});
|
|
|
|
/**
|
|
* The currently active debug mode names, and names to skip.
|
|
*/
|
|
|
|
createDebug.names = [];
|
|
createDebug.skips = [];
|
|
|
|
/**
|
|
* Map of special "%n" handling functions, for the debug "format" argument.
|
|
*
|
|
* Valid key names are a single, lower or upper-case letter, i.e. "n" and "N".
|
|
*/
|
|
createDebug.formatters = {};
|
|
|
|
/**
|
|
* Selects a color for a debug namespace
|
|
* @param {String} namespace The namespace string for the debug instance to be colored
|
|
* @return {Number|String} An ANSI color code for the given namespace
|
|
* @api private
|
|
*/
|
|
function selectColor(namespace) {
|
|
let hash = 0;
|
|
|
|
for (let i = 0; i < namespace.length; i++) {
|
|
hash = ((hash << 5) - hash) + namespace.charCodeAt(i);
|
|
hash |= 0; // Convert to 32bit integer
|
|
}
|
|
|
|
return createDebug.colors[Math.abs(hash) % createDebug.colors.length];
|
|
}
|
|
createDebug.selectColor = selectColor;
|
|
|
|
/**
|
|
* Create a debugger with the given `namespace`.
|
|
*
|
|
* @param {String} namespace
|
|
* @return {Function}
|
|
* @api public
|
|
*/
|
|
function createDebug(namespace) {
|
|
let prevTime;
|
|
let enableOverride = null;
|
|
let namespacesCache;
|
|
let enabledCache;
|
|
|
|
function debug(...args) {
|
|
// Disabled?
|
|
if (!debug.enabled) {
|
|
return;
|
|
}
|
|
|
|
const self = debug;
|
|
|
|
// Set `diff` timestamp
|
|
const curr = Number(new Date());
|
|
const ms = curr - (prevTime || curr);
|
|
self.diff = ms;
|
|
self.prev = prevTime;
|
|
self.curr = curr;
|
|
prevTime = curr;
|
|
|
|
args[0] = createDebug.coerce(args[0]);
|
|
|
|
if (typeof args[0] !== 'string') {
|
|
// Anything else let's inspect with %O
|
|
args.unshift('%O');
|
|
}
|
|
|
|
// Apply any `formatters` transformations
|
|
let index = 0;
|
|
args[0] = args[0].replace(/%([a-zA-Z%])/g, (match, format) => {
|
|
// If we encounter an escaped % then don't increase the array index
|
|
if (match === '%%') {
|
|
return '%';
|
|
}
|
|
index++;
|
|
const formatter = createDebug.formatters[format];
|
|
if (typeof formatter === 'function') {
|
|
const val = args[index];
|
|
match = formatter.call(self, val);
|
|
|
|
// Now we need to remove `args[index]` since it's inlined in the `format`
|
|
args.splice(index, 1);
|
|
index--;
|
|
}
|
|
return match;
|
|
});
|
|
|
|
// Apply env-specific formatting (colors, etc.)
|
|
createDebug.formatArgs.call(self, args);
|
|
|
|
const logFn = self.log || createDebug.log;
|
|
logFn.apply(self, args);
|
|
}
|
|
|
|
debug.namespace = namespace;
|
|
debug.useColors = createDebug.useColors();
|
|
debug.color = createDebug.selectColor(namespace);
|
|
debug.extend = extend;
|
|
debug.destroy = createDebug.destroy; // XXX Temporary. Will be removed in the next major release.
|
|
|
|
Object.defineProperty(debug, 'enabled', {
|
|
enumerable: true,
|
|
configurable: false,
|
|
get: () => {
|
|
if (enableOverride !== null) {
|
|
return enableOverride;
|
|
}
|
|
if (namespacesCache !== createDebug.namespaces) {
|
|
namespacesCache = createDebug.namespaces;
|
|
enabledCache = createDebug.enabled(namespace);
|
|
}
|
|
|
|
return enabledCache;
|
|
},
|
|
set: v => {
|
|
enableOverride = v;
|
|
}
|
|
});
|
|
|
|
// Env-specific initialization logic for debug instances
|
|
if (typeof createDebug.init === 'function') {
|
|
createDebug.init(debug);
|
|
}
|
|
|
|
return debug;
|
|
}
|
|
|
|
function extend(namespace, delimiter) {
|
|
const newDebug = createDebug(this.namespace + (typeof delimiter === 'undefined' ? ':' : delimiter) + namespace);
|
|
newDebug.log = this.log;
|
|
return newDebug;
|
|
}
|
|
|
|
/**
|
|
* Enables a debug mode by namespaces. This can include modes
|
|
* separated by a colon and wildcards.
|
|
*
|
|
* @param {String} namespaces
|
|
* @api public
|
|
*/
|
|
function enable(namespaces) {
|
|
createDebug.save(namespaces);
|
|
createDebug.namespaces = namespaces;
|
|
|
|
createDebug.names = [];
|
|
createDebug.skips = [];
|
|
|
|
let i;
|
|
const split = (typeof namespaces === 'string' ? namespaces : '').split(/[\s,]+/);
|
|
const len = split.length;
|
|
|
|
for (i = 0; i < len; i++) {
|
|
if (!split[i]) {
|
|
// ignore empty strings
|
|
continue;
|
|
}
|
|
|
|
namespaces = split[i].replace(/\*/g, '.*?');
|
|
|
|
if (namespaces[0] === '-') {
|
|
createDebug.skips.push(new RegExp('^' + namespaces.slice(1) + '$'));
|
|
} else {
|
|
createDebug.names.push(new RegExp('^' + namespaces + '$'));
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Disable debug output.
|
|
*
|
|
* @return {String} namespaces
|
|
* @api public
|
|
*/
|
|
function disable() {
|
|
const namespaces = [
|
|
...createDebug.names.map(toNamespace),
|
|
...createDebug.skips.map(toNamespace).map(namespace => '-' + namespace)
|
|
].join(',');
|
|
createDebug.enable('');
|
|
return namespaces;
|
|
}
|
|
|
|
/**
|
|
* Returns true if the given mode name is enabled, false otherwise.
|
|
*
|
|
* @param {String} name
|
|
* @return {Boolean}
|
|
* @api public
|
|
*/
|
|
function enabled(name) {
|
|
if (name[name.length - 1] === '*') {
|
|
return true;
|
|
}
|
|
|
|
let i;
|
|
let len;
|
|
|
|
for (i = 0, len = createDebug.skips.length; i < len; i++) {
|
|
if (createDebug.skips[i].test(name)) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
for (i = 0, len = createDebug.names.length; i < len; i++) {
|
|
if (createDebug.names[i].test(name)) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Convert regexp to namespace
|
|
*
|
|
* @param {RegExp} regxep
|
|
* @return {String} namespace
|
|
* @api private
|
|
*/
|
|
function toNamespace(regexp) {
|
|
return regexp.toString()
|
|
.substring(2, regexp.toString().length - 2)
|
|
.replace(/\.\*\?$/, '*');
|
|
}
|
|
|
|
/**
|
|
* Coerce `val`.
|
|
*
|
|
* @param {Mixed} val
|
|
* @return {Mixed}
|
|
* @api private
|
|
*/
|
|
function coerce(val) {
|
|
if (val instanceof Error) {
|
|
return val.stack || val.message;
|
|
}
|
|
return val;
|
|
}
|
|
|
|
/**
|
|
* XXX DO NOT USE. This is a temporary stub function.
|
|
* XXX It WILL be removed in the next major release.
|
|
*/
|
|
function destroy() {
|
|
console.warn('Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.');
|
|
}
|
|
|
|
createDebug.enable(createDebug.load());
|
|
|
|
return createDebug;
|
|
}
|
|
|
|
common = setup;
|
|
return common;
|
|
}
|
|
|
|
/* eslint-env browser */
|
|
|
|
var hasRequiredBrowser;
|
|
|
|
function requireBrowser () {
|
|
if (hasRequiredBrowser) return browser$1.exports;
|
|
hasRequiredBrowser = 1;
|
|
(function (module, exports) {
|
|
/**
|
|
* This is the web browser implementation of `debug()`.
|
|
*/
|
|
|
|
exports.formatArgs = formatArgs;
|
|
exports.save = save;
|
|
exports.load = load;
|
|
exports.useColors = useColors;
|
|
exports.storage = localstorage();
|
|
exports.destroy = (() => {
|
|
let warned = false;
|
|
|
|
return () => {
|
|
if (!warned) {
|
|
warned = true;
|
|
console.warn('Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.');
|
|
}
|
|
};
|
|
})();
|
|
|
|
/**
|
|
* Colors.
|
|
*/
|
|
|
|
exports.colors = [
|
|
'#0000CC',
|
|
'#0000FF',
|
|
'#0033CC',
|
|
'#0033FF',
|
|
'#0066CC',
|
|
'#0066FF',
|
|
'#0099CC',
|
|
'#0099FF',
|
|
'#00CC00',
|
|
'#00CC33',
|
|
'#00CC66',
|
|
'#00CC99',
|
|
'#00CCCC',
|
|
'#00CCFF',
|
|
'#3300CC',
|
|
'#3300FF',
|
|
'#3333CC',
|
|
'#3333FF',
|
|
'#3366CC',
|
|
'#3366FF',
|
|
'#3399CC',
|
|
'#3399FF',
|
|
'#33CC00',
|
|
'#33CC33',
|
|
'#33CC66',
|
|
'#33CC99',
|
|
'#33CCCC',
|
|
'#33CCFF',
|
|
'#6600CC',
|
|
'#6600FF',
|
|
'#6633CC',
|
|
'#6633FF',
|
|
'#66CC00',
|
|
'#66CC33',
|
|
'#9900CC',
|
|
'#9900FF',
|
|
'#9933CC',
|
|
'#9933FF',
|
|
'#99CC00',
|
|
'#99CC33',
|
|
'#CC0000',
|
|
'#CC0033',
|
|
'#CC0066',
|
|
'#CC0099',
|
|
'#CC00CC',
|
|
'#CC00FF',
|
|
'#CC3300',
|
|
'#CC3333',
|
|
'#CC3366',
|
|
'#CC3399',
|
|
'#CC33CC',
|
|
'#CC33FF',
|
|
'#CC6600',
|
|
'#CC6633',
|
|
'#CC9900',
|
|
'#CC9933',
|
|
'#CCCC00',
|
|
'#CCCC33',
|
|
'#FF0000',
|
|
'#FF0033',
|
|
'#FF0066',
|
|
'#FF0099',
|
|
'#FF00CC',
|
|
'#FF00FF',
|
|
'#FF3300',
|
|
'#FF3333',
|
|
'#FF3366',
|
|
'#FF3399',
|
|
'#FF33CC',
|
|
'#FF33FF',
|
|
'#FF6600',
|
|
'#FF6633',
|
|
'#FF9900',
|
|
'#FF9933',
|
|
'#FFCC00',
|
|
'#FFCC33'
|
|
];
|
|
|
|
/**
|
|
* Currently only WebKit-based Web Inspectors, Firefox >= v31,
|
|
* and the Firebug extension (any Firefox version) are known
|
|
* to support "%c" CSS customizations.
|
|
*
|
|
* TODO: add a `localStorage` variable to explicitly enable/disable colors
|
|
*/
|
|
|
|
// eslint-disable-next-line complexity
|
|
function useColors() {
|
|
// NB: In an Electron preload script, document will be defined but not fully
|
|
// initialized. Since we know we're in Chrome, we'll just detect this case
|
|
// explicitly
|
|
if (typeof window !== 'undefined' && window.process && (window.process.type === 'renderer' || window.process.__nwjs)) {
|
|
return true;
|
|
}
|
|
|
|
// Internet Explorer and Edge do not support colors.
|
|
if (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/(edge|trident)\/(\d+)/)) {
|
|
return false;
|
|
}
|
|
|
|
// Is webkit? http://stackoverflow.com/a/16459606/376773
|
|
// document is undefined in react-native: https://github.com/facebook/react-native/pull/1632
|
|
return (typeof document !== 'undefined' && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance) ||
|
|
// Is firebug? http://stackoverflow.com/a/398120/376773
|
|
(typeof window !== 'undefined' && window.console && (window.console.firebug || (window.console.exception && window.console.table))) ||
|
|
// Is firefox >= v31?
|
|
// https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages
|
|
(typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31) ||
|
|
// Double check webkit in userAgent just in case we are in a worker
|
|
(typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/));
|
|
}
|
|
|
|
/**
|
|
* Colorize log arguments if enabled.
|
|
*
|
|
* @api public
|
|
*/
|
|
|
|
function formatArgs(args) {
|
|
args[0] = (this.useColors ? '%c' : '') +
|
|
this.namespace +
|
|
(this.useColors ? ' %c' : ' ') +
|
|
args[0] +
|
|
(this.useColors ? '%c ' : ' ') +
|
|
'+' + module.exports.humanize(this.diff);
|
|
|
|
if (!this.useColors) {
|
|
return;
|
|
}
|
|
|
|
const c = 'color: ' + this.color;
|
|
args.splice(1, 0, c, 'color: inherit');
|
|
|
|
// The final "%c" is somewhat tricky, because there could be other
|
|
// arguments passed either before or after the %c, so we need to
|
|
// figure out the correct index to insert the CSS into
|
|
let index = 0;
|
|
let lastC = 0;
|
|
args[0].replace(/%[a-zA-Z%]/g, match => {
|
|
if (match === '%%') {
|
|
return;
|
|
}
|
|
index++;
|
|
if (match === '%c') {
|
|
// We only are interested in the *last* %c
|
|
// (the user may have provided their own)
|
|
lastC = index;
|
|
}
|
|
});
|
|
|
|
args.splice(lastC, 0, c);
|
|
}
|
|
|
|
/**
|
|
* Invokes `console.debug()` when available.
|
|
* No-op when `console.debug` is not a "function".
|
|
* If `console.debug` is not available, falls back
|
|
* to `console.log`.
|
|
*
|
|
* @api public
|
|
*/
|
|
exports.log = console.debug || console.log || (() => {});
|
|
|
|
/**
|
|
* Save `namespaces`.
|
|
*
|
|
* @param {String} namespaces
|
|
* @api private
|
|
*/
|
|
function save(namespaces) {
|
|
try {
|
|
if (namespaces) {
|
|
exports.storage.setItem('debug', namespaces);
|
|
} else {
|
|
exports.storage.removeItem('debug');
|
|
}
|
|
} catch (error) {
|
|
// Swallow
|
|
// XXX (@Qix-) should we be logging these?
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Load `namespaces`.
|
|
*
|
|
* @return {String} returns the previously persisted debug modes
|
|
* @api private
|
|
*/
|
|
function load() {
|
|
let r;
|
|
try {
|
|
r = exports.storage.getItem('debug');
|
|
} catch (error) {
|
|
// Swallow
|
|
// XXX (@Qix-) should we be logging these?
|
|
}
|
|
|
|
// If debug isn't set in LS, and we're in Electron, try to load $DEBUG
|
|
if (!r && typeof process !== 'undefined' && 'env' in process) {
|
|
r = process.env.DEBUG;
|
|
}
|
|
|
|
return r;
|
|
}
|
|
|
|
/**
|
|
* Localstorage attempts to return the localstorage.
|
|
*
|
|
* This is necessary because safari throws
|
|
* when a user disables cookies/localstorage
|
|
* and you attempt to access it.
|
|
*
|
|
* @return {LocalStorage}
|
|
* @api private
|
|
*/
|
|
|
|
function localstorage() {
|
|
try {
|
|
// TVMLKit (Apple TV JS Runtime) does not have a window object, just localStorage in the global context
|
|
// The Browser also has localStorage in the global context.
|
|
return localStorage;
|
|
} catch (error) {
|
|
// Swallow
|
|
// XXX (@Qix-) should we be logging these?
|
|
}
|
|
}
|
|
|
|
module.exports = requireCommon()(exports);
|
|
|
|
const {formatters} = module.exports;
|
|
|
|
/**
|
|
* Map %j to `JSON.stringify()`, since no Web Inspectors do that by default.
|
|
*/
|
|
|
|
formatters.j = function (v) {
|
|
try {
|
|
return JSON.stringify(v);
|
|
} catch (error) {
|
|
return '[UnexpectedJSONParseError]: ' + error.message;
|
|
}
|
|
};
|
|
} (browser$1, browser$1.exports));
|
|
return browser$1.exports;
|
|
}
|
|
|
|
var node = {exports: {}};
|
|
|
|
/**
|
|
* Module dependencies.
|
|
*/
|
|
|
|
var hasRequiredNode;
|
|
|
|
function requireNode () {
|
|
if (hasRequiredNode) return node.exports;
|
|
hasRequiredNode = 1;
|
|
(function (module, exports) {
|
|
const tty = require$$0;
|
|
const util = require$$1;
|
|
|
|
/**
|
|
* This is the Node.js implementation of `debug()`.
|
|
*/
|
|
|
|
exports.init = init;
|
|
exports.log = log;
|
|
exports.formatArgs = formatArgs;
|
|
exports.save = save;
|
|
exports.load = load;
|
|
exports.useColors = useColors;
|
|
exports.destroy = util.deprecate(
|
|
() => {},
|
|
'Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.'
|
|
);
|
|
|
|
/**
|
|
* Colors.
|
|
*/
|
|
|
|
exports.colors = [6, 2, 3, 4, 5, 1];
|
|
|
|
try {
|
|
// Optional dependency (as in, doesn't need to be installed, NOT like optionalDependencies in package.json)
|
|
// eslint-disable-next-line import/no-extraneous-dependencies
|
|
const supportsColor = require('supports-color');
|
|
|
|
if (supportsColor && (supportsColor.stderr || supportsColor).level >= 2) {
|
|
exports.colors = [
|
|
20,
|
|
21,
|
|
26,
|
|
27,
|
|
32,
|
|
33,
|
|
38,
|
|
39,
|
|
40,
|
|
41,
|
|
42,
|
|
43,
|
|
44,
|
|
45,
|
|
56,
|
|
57,
|
|
62,
|
|
63,
|
|
68,
|
|
69,
|
|
74,
|
|
75,
|
|
76,
|
|
77,
|
|
78,
|
|
79,
|
|
80,
|
|
81,
|
|
92,
|
|
93,
|
|
98,
|
|
99,
|
|
112,
|
|
113,
|
|
128,
|
|
129,
|
|
134,
|
|
135,
|
|
148,
|
|
149,
|
|
160,
|
|
161,
|
|
162,
|
|
163,
|
|
164,
|
|
165,
|
|
166,
|
|
167,
|
|
168,
|
|
169,
|
|
170,
|
|
171,
|
|
172,
|
|
173,
|
|
178,
|
|
179,
|
|
184,
|
|
185,
|
|
196,
|
|
197,
|
|
198,
|
|
199,
|
|
200,
|
|
201,
|
|
202,
|
|
203,
|
|
204,
|
|
205,
|
|
206,
|
|
207,
|
|
208,
|
|
209,
|
|
214,
|
|
215,
|
|
220,
|
|
221
|
|
];
|
|
}
|
|
} catch (error) {
|
|
// Swallow - we only care if `supports-color` is available; it doesn't have to be.
|
|
}
|
|
|
|
/**
|
|
* Build up the default `inspectOpts` object from the environment variables.
|
|
*
|
|
* $ DEBUG_COLORS=no DEBUG_DEPTH=10 DEBUG_SHOW_HIDDEN=enabled node script.js
|
|
*/
|
|
|
|
exports.inspectOpts = Object.keys(process.env).filter(key => {
|
|
return /^debug_/i.test(key);
|
|
}).reduce((obj, key) => {
|
|
// Camel-case
|
|
const prop = key
|
|
.substring(6)
|
|
.toLowerCase()
|
|
.replace(/_([a-z])/g, (_, k) => {
|
|
return k.toUpperCase();
|
|
});
|
|
|
|
// Coerce string value into JS value
|
|
let val = process.env[key];
|
|
if (/^(yes|on|true|enabled)$/i.test(val)) {
|
|
val = true;
|
|
} else if (/^(no|off|false|disabled)$/i.test(val)) {
|
|
val = false;
|
|
} else if (val === 'null') {
|
|
val = null;
|
|
} else {
|
|
val = Number(val);
|
|
}
|
|
|
|
obj[prop] = val;
|
|
return obj;
|
|
}, {});
|
|
|
|
/**
|
|
* Is stdout a TTY? Colored output is enabled when `true`.
|
|
*/
|
|
|
|
function useColors() {
|
|
return 'colors' in exports.inspectOpts ?
|
|
Boolean(exports.inspectOpts.colors) :
|
|
tty.isatty(process.stderr.fd);
|
|
}
|
|
|
|
/**
|
|
* Adds ANSI color escape codes if enabled.
|
|
*
|
|
* @api public
|
|
*/
|
|
|
|
function formatArgs(args) {
|
|
const {namespace: name, useColors} = this;
|
|
|
|
if (useColors) {
|
|
const c = this.color;
|
|
const colorCode = '\u001B[3' + (c < 8 ? c : '8;5;' + c);
|
|
const prefix = ` ${colorCode};1m${name} \u001B[0m`;
|
|
|
|
args[0] = prefix + args[0].split('\n').join('\n' + prefix);
|
|
args.push(colorCode + 'm+' + module.exports.humanize(this.diff) + '\u001B[0m');
|
|
} else {
|
|
args[0] = getDate() + name + ' ' + args[0];
|
|
}
|
|
}
|
|
|
|
function getDate() {
|
|
if (exports.inspectOpts.hideDate) {
|
|
return '';
|
|
}
|
|
return new Date().toISOString() + ' ';
|
|
}
|
|
|
|
/**
|
|
* Invokes `util.format()` with the specified arguments and writes to stderr.
|
|
*/
|
|
|
|
function log(...args) {
|
|
return process.stderr.write(util.format(...args) + '\n');
|
|
}
|
|
|
|
/**
|
|
* Save `namespaces`.
|
|
*
|
|
* @param {String} namespaces
|
|
* @api private
|
|
*/
|
|
function save(namespaces) {
|
|
if (namespaces) {
|
|
process.env.DEBUG = namespaces;
|
|
} else {
|
|
// If you set a process.env field to null or undefined, it gets cast to the
|
|
// string 'null' or 'undefined'. Just delete instead.
|
|
delete process.env.DEBUG;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Load `namespaces`.
|
|
*
|
|
* @return {String} returns the previously persisted debug modes
|
|
* @api private
|
|
*/
|
|
|
|
function load() {
|
|
return process.env.DEBUG;
|
|
}
|
|
|
|
/**
|
|
* Init logic for `debug` instances.
|
|
*
|
|
* Create a new `inspectOpts` object in case `useColors` is set
|
|
* differently for a particular `debug` instance.
|
|
*/
|
|
|
|
function init(debug) {
|
|
debug.inspectOpts = {};
|
|
|
|
const keys = Object.keys(exports.inspectOpts);
|
|
for (let i = 0; i < keys.length; i++) {
|
|
debug.inspectOpts[keys[i]] = exports.inspectOpts[keys[i]];
|
|
}
|
|
}
|
|
|
|
module.exports = requireCommon()(exports);
|
|
|
|
const {formatters} = module.exports;
|
|
|
|
/**
|
|
* Map %o to `util.inspect()`, all on a single line.
|
|
*/
|
|
|
|
formatters.o = function (v) {
|
|
this.inspectOpts.colors = this.useColors;
|
|
return util.inspect(v, this.inspectOpts)
|
|
.split('\n')
|
|
.map(str => str.trim())
|
|
.join(' ');
|
|
};
|
|
|
|
/**
|
|
* Map %O to `util.inspect()`, allowing multiple lines if needed.
|
|
*/
|
|
|
|
formatters.O = function (v) {
|
|
this.inspectOpts.colors = this.useColors;
|
|
return util.inspect(v, this.inspectOpts);
|
|
};
|
|
} (node, node.exports));
|
|
return node.exports;
|
|
}
|
|
|
|
/**
|
|
* Detect Electron renderer / nwjs process, which is node, but we should
|
|
* treat as a browser.
|
|
*/
|
|
|
|
if (typeof process === 'undefined' || process.type === 'renderer' || process.browser === true || process.__nwjs) {
|
|
src.exports = requireBrowser();
|
|
} else {
|
|
src.exports = requireNode();
|
|
}
|
|
|
|
var srcExports = src.exports;
|
|
var debug$1 = /*@__PURE__*/getDefaultExportFromCjs(srcExports);
|
|
|
|
var utils$3 = {};
|
|
|
|
const path$2 = require$$0$1;
|
|
const WIN_SLASH = '\\\\/';
|
|
const WIN_NO_SLASH = `[^${WIN_SLASH}]`;
|
|
|
|
/**
|
|
* Posix glob regex
|
|
*/
|
|
|
|
const DOT_LITERAL = '\\.';
|
|
const PLUS_LITERAL = '\\+';
|
|
const QMARK_LITERAL = '\\?';
|
|
const SLASH_LITERAL = '\\/';
|
|
const ONE_CHAR = '(?=.)';
|
|
const QMARK = '[^/]';
|
|
const END_ANCHOR = `(?:${SLASH_LITERAL}|$)`;
|
|
const START_ANCHOR = `(?:^|${SLASH_LITERAL})`;
|
|
const DOTS_SLASH = `${DOT_LITERAL}{1,2}${END_ANCHOR}`;
|
|
const NO_DOT = `(?!${DOT_LITERAL})`;
|
|
const NO_DOTS = `(?!${START_ANCHOR}${DOTS_SLASH})`;
|
|
const NO_DOT_SLASH = `(?!${DOT_LITERAL}{0,1}${END_ANCHOR})`;
|
|
const NO_DOTS_SLASH = `(?!${DOTS_SLASH})`;
|
|
const QMARK_NO_DOT = `[^.${SLASH_LITERAL}]`;
|
|
const STAR = `${QMARK}*?`;
|
|
|
|
const POSIX_CHARS = {
|
|
DOT_LITERAL,
|
|
PLUS_LITERAL,
|
|
QMARK_LITERAL,
|
|
SLASH_LITERAL,
|
|
ONE_CHAR,
|
|
QMARK,
|
|
END_ANCHOR,
|
|
DOTS_SLASH,
|
|
NO_DOT,
|
|
NO_DOTS,
|
|
NO_DOT_SLASH,
|
|
NO_DOTS_SLASH,
|
|
QMARK_NO_DOT,
|
|
STAR,
|
|
START_ANCHOR
|
|
};
|
|
|
|
/**
|
|
* Windows glob regex
|
|
*/
|
|
|
|
const WINDOWS_CHARS = {
|
|
...POSIX_CHARS,
|
|
|
|
SLASH_LITERAL: `[${WIN_SLASH}]`,
|
|
QMARK: WIN_NO_SLASH,
|
|
STAR: `${WIN_NO_SLASH}*?`,
|
|
DOTS_SLASH: `${DOT_LITERAL}{1,2}(?:[${WIN_SLASH}]|$)`,
|
|
NO_DOT: `(?!${DOT_LITERAL})`,
|
|
NO_DOTS: `(?!(?:^|[${WIN_SLASH}])${DOT_LITERAL}{1,2}(?:[${WIN_SLASH}]|$))`,
|
|
NO_DOT_SLASH: `(?!${DOT_LITERAL}{0,1}(?:[${WIN_SLASH}]|$))`,
|
|
NO_DOTS_SLASH: `(?!${DOT_LITERAL}{1,2}(?:[${WIN_SLASH}]|$))`,
|
|
QMARK_NO_DOT: `[^.${WIN_SLASH}]`,
|
|
START_ANCHOR: `(?:^|[${WIN_SLASH}])`,
|
|
END_ANCHOR: `(?:[${WIN_SLASH}]|$)`
|
|
};
|
|
|
|
/**
|
|
* POSIX Bracket Regex
|
|
*/
|
|
|
|
const POSIX_REGEX_SOURCE$1 = {
|
|
alnum: 'a-zA-Z0-9',
|
|
alpha: 'a-zA-Z',
|
|
ascii: '\\x00-\\x7F',
|
|
blank: ' \\t',
|
|
cntrl: '\\x00-\\x1F\\x7F',
|
|
digit: '0-9',
|
|
graph: '\\x21-\\x7E',
|
|
lower: 'a-z',
|
|
print: '\\x20-\\x7E ',
|
|
punct: '\\-!"#$%&\'()\\*+,./:;<=>?@[\\]^_`{|}~',
|
|
space: ' \\t\\r\\n\\v\\f',
|
|
upper: 'A-Z',
|
|
word: 'A-Za-z0-9_',
|
|
xdigit: 'A-Fa-f0-9'
|
|
};
|
|
|
|
var constants$2 = {
|
|
MAX_LENGTH: 1024 * 64,
|
|
POSIX_REGEX_SOURCE: POSIX_REGEX_SOURCE$1,
|
|
|
|
// regular expressions
|
|
REGEX_BACKSLASH: /\\(?![*+?^${}(|)[\]])/g,
|
|
REGEX_NON_SPECIAL_CHARS: /^[^@![\].,$*+?^{}()|\\/]+/,
|
|
REGEX_SPECIAL_CHARS: /[-*+?.^${}(|)[\]]/,
|
|
REGEX_SPECIAL_CHARS_BACKREF: /(\\?)((\W)(\3*))/g,
|
|
REGEX_SPECIAL_CHARS_GLOBAL: /([-*+?.^${}(|)[\]])/g,
|
|
REGEX_REMOVE_BACKSLASH: /(?:\[.*?[^\\]\]|\\(?=.))/g,
|
|
|
|
// Replace globs with equivalent patterns to reduce parsing time.
|
|
REPLACEMENTS: {
|
|
'***': '*',
|
|
'**/**': '**',
|
|
'**/**/**': '**'
|
|
},
|
|
|
|
// Digits
|
|
CHAR_0: 48, /* 0 */
|
|
CHAR_9: 57, /* 9 */
|
|
|
|
// Alphabet chars.
|
|
CHAR_UPPERCASE_A: 65, /* A */
|
|
CHAR_LOWERCASE_A: 97, /* a */
|
|
CHAR_UPPERCASE_Z: 90, /* Z */
|
|
CHAR_LOWERCASE_Z: 122, /* z */
|
|
|
|
CHAR_LEFT_PARENTHESES: 40, /* ( */
|
|
CHAR_RIGHT_PARENTHESES: 41, /* ) */
|
|
|
|
CHAR_ASTERISK: 42, /* * */
|
|
|
|
// Non-alphabetic chars.
|
|
CHAR_AMPERSAND: 38, /* & */
|
|
CHAR_AT: 64, /* @ */
|
|
CHAR_BACKWARD_SLASH: 92, /* \ */
|
|
CHAR_CARRIAGE_RETURN: 13, /* \r */
|
|
CHAR_CIRCUMFLEX_ACCENT: 94, /* ^ */
|
|
CHAR_COLON: 58, /* : */
|
|
CHAR_COMMA: 44, /* , */
|
|
CHAR_DOT: 46, /* . */
|
|
CHAR_DOUBLE_QUOTE: 34, /* " */
|
|
CHAR_EQUAL: 61, /* = */
|
|
CHAR_EXCLAMATION_MARK: 33, /* ! */
|
|
CHAR_FORM_FEED: 12, /* \f */
|
|
CHAR_FORWARD_SLASH: 47, /* / */
|
|
CHAR_GRAVE_ACCENT: 96, /* ` */
|
|
CHAR_HASH: 35, /* # */
|
|
CHAR_HYPHEN_MINUS: 45, /* - */
|
|
CHAR_LEFT_ANGLE_BRACKET: 60, /* < */
|
|
CHAR_LEFT_CURLY_BRACE: 123, /* { */
|
|
CHAR_LEFT_SQUARE_BRACKET: 91, /* [ */
|
|
CHAR_LINE_FEED: 10, /* \n */
|
|
CHAR_NO_BREAK_SPACE: 160, /* \u00A0 */
|
|
CHAR_PERCENT: 37, /* % */
|
|
CHAR_PLUS: 43, /* + */
|
|
CHAR_QUESTION_MARK: 63, /* ? */
|
|
CHAR_RIGHT_ANGLE_BRACKET: 62, /* > */
|
|
CHAR_RIGHT_CURLY_BRACE: 125, /* } */
|
|
CHAR_RIGHT_SQUARE_BRACKET: 93, /* ] */
|
|
CHAR_SEMICOLON: 59, /* ; */
|
|
CHAR_SINGLE_QUOTE: 39, /* ' */
|
|
CHAR_SPACE: 32, /* */
|
|
CHAR_TAB: 9, /* \t */
|
|
CHAR_UNDERSCORE: 95, /* _ */
|
|
CHAR_VERTICAL_LINE: 124, /* | */
|
|
CHAR_ZERO_WIDTH_NOBREAK_SPACE: 65279, /* \uFEFF */
|
|
|
|
SEP: path$2.sep,
|
|
|
|
/**
|
|
* Create EXTGLOB_CHARS
|
|
*/
|
|
|
|
extglobChars(chars) {
|
|
return {
|
|
'!': { type: 'negate', open: '(?:(?!(?:', close: `))${chars.STAR})` },
|
|
'?': { type: 'qmark', open: '(?:', close: ')?' },
|
|
'+': { type: 'plus', open: '(?:', close: ')+' },
|
|
'*': { type: 'star', open: '(?:', close: ')*' },
|
|
'@': { type: 'at', open: '(?:', close: ')' }
|
|
};
|
|
},
|
|
|
|
/**
|
|
* Create GLOB_CHARS
|
|
*/
|
|
|
|
globChars(win32) {
|
|
return win32 === true ? WINDOWS_CHARS : POSIX_CHARS;
|
|
}
|
|
};
|
|
|
|
(function (exports) {
|
|
|
|
const path = require$$0$1;
|
|
const win32 = process.platform === 'win32';
|
|
const {
|
|
REGEX_BACKSLASH,
|
|
REGEX_REMOVE_BACKSLASH,
|
|
REGEX_SPECIAL_CHARS,
|
|
REGEX_SPECIAL_CHARS_GLOBAL
|
|
} = constants$2;
|
|
|
|
exports.isObject = val => val !== null && typeof val === 'object' && !Array.isArray(val);
|
|
exports.hasRegexChars = str => REGEX_SPECIAL_CHARS.test(str);
|
|
exports.isRegexChar = str => str.length === 1 && exports.hasRegexChars(str);
|
|
exports.escapeRegex = str => str.replace(REGEX_SPECIAL_CHARS_GLOBAL, '\\$1');
|
|
exports.toPosixSlashes = str => str.replace(REGEX_BACKSLASH, '/');
|
|
|
|
exports.removeBackslashes = str => {
|
|
return str.replace(REGEX_REMOVE_BACKSLASH, match => {
|
|
return match === '\\' ? '' : match;
|
|
});
|
|
};
|
|
|
|
exports.supportsLookbehinds = () => {
|
|
const segs = process.version.slice(1).split('.').map(Number);
|
|
if (segs.length === 3 && segs[0] >= 9 || (segs[0] === 8 && segs[1] >= 10)) {
|
|
return true;
|
|
}
|
|
return false;
|
|
};
|
|
|
|
exports.isWindows = options => {
|
|
if (options && typeof options.windows === 'boolean') {
|
|
return options.windows;
|
|
}
|
|
return win32 === true || path.sep === '\\';
|
|
};
|
|
|
|
exports.escapeLast = (input, char, lastIdx) => {
|
|
const idx = input.lastIndexOf(char, lastIdx);
|
|
if (idx === -1) return input;
|
|
if (input[idx - 1] === '\\') return exports.escapeLast(input, char, idx - 1);
|
|
return `${input.slice(0, idx)}\\${input.slice(idx)}`;
|
|
};
|
|
|
|
exports.removePrefix = (input, state = {}) => {
|
|
let output = input;
|
|
if (output.startsWith('./')) {
|
|
output = output.slice(2);
|
|
state.prefix = './';
|
|
}
|
|
return output;
|
|
};
|
|
|
|
exports.wrapOutput = (input, state = {}, options = {}) => {
|
|
const prepend = options.contains ? '' : '^';
|
|
const append = options.contains ? '' : '$';
|
|
|
|
let output = `${prepend}(?:${input})${append}`;
|
|
if (state.negated === true) {
|
|
output = `(?:^(?!${output}).*$)`;
|
|
}
|
|
return output;
|
|
};
|
|
} (utils$3));
|
|
|
|
const utils$2 = utils$3;
|
|
const {
|
|
CHAR_ASTERISK, /* * */
|
|
CHAR_AT, /* @ */
|
|
CHAR_BACKWARD_SLASH, /* \ */
|
|
CHAR_COMMA, /* , */
|
|
CHAR_DOT, /* . */
|
|
CHAR_EXCLAMATION_MARK, /* ! */
|
|
CHAR_FORWARD_SLASH, /* / */
|
|
CHAR_LEFT_CURLY_BRACE, /* { */
|
|
CHAR_LEFT_PARENTHESES, /* ( */
|
|
CHAR_LEFT_SQUARE_BRACKET, /* [ */
|
|
CHAR_PLUS, /* + */
|
|
CHAR_QUESTION_MARK, /* ? */
|
|
CHAR_RIGHT_CURLY_BRACE, /* } */
|
|
CHAR_RIGHT_PARENTHESES, /* ) */
|
|
CHAR_RIGHT_SQUARE_BRACKET /* ] */
|
|
} = constants$2;
|
|
|
|
const isPathSeparator = code => {
|
|
return code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH;
|
|
};
|
|
|
|
const depth = token => {
|
|
if (token.isPrefix !== true) {
|
|
token.depth = token.isGlobstar ? Infinity : 1;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Quickly scans a glob pattern and returns an object with a handful of
|
|
* useful properties, like `isGlob`, `path` (the leading non-glob, if it exists),
|
|
* `glob` (the actual pattern), `negated` (true if the path starts with `!` but not
|
|
* with `!(`) and `negatedExtglob` (true if the path starts with `!(`).
|
|
*
|
|
* ```js
|
|
* const pm = require('picomatch');
|
|
* console.log(pm.scan('foo/bar/*.js'));
|
|
* { isGlob: true, input: 'foo/bar/*.js', base: 'foo/bar', glob: '*.js' }
|
|
* ```
|
|
* @param {String} `str`
|
|
* @param {Object} `options`
|
|
* @return {Object} Returns an object with tokens and regex source string.
|
|
* @api public
|
|
*/
|
|
|
|
const scan$1 = (input, options) => {
|
|
const opts = options || {};
|
|
|
|
const length = input.length - 1;
|
|
const scanToEnd = opts.parts === true || opts.scanToEnd === true;
|
|
const slashes = [];
|
|
const tokens = [];
|
|
const parts = [];
|
|
|
|
let str = input;
|
|
let index = -1;
|
|
let start = 0;
|
|
let lastIndex = 0;
|
|
let isBrace = false;
|
|
let isBracket = false;
|
|
let isGlob = false;
|
|
let isExtglob = false;
|
|
let isGlobstar = false;
|
|
let braceEscaped = false;
|
|
let backslashes = false;
|
|
let negated = false;
|
|
let negatedExtglob = false;
|
|
let finished = false;
|
|
let braces = 0;
|
|
let prev;
|
|
let code;
|
|
let token = { value: '', depth: 0, isGlob: false };
|
|
|
|
const eos = () => index >= length;
|
|
const peek = () => str.charCodeAt(index + 1);
|
|
const advance = () => {
|
|
prev = code;
|
|
return str.charCodeAt(++index);
|
|
};
|
|
|
|
while (index < length) {
|
|
code = advance();
|
|
let next;
|
|
|
|
if (code === CHAR_BACKWARD_SLASH) {
|
|
backslashes = token.backslashes = true;
|
|
code = advance();
|
|
|
|
if (code === CHAR_LEFT_CURLY_BRACE) {
|
|
braceEscaped = true;
|
|
}
|
|
continue;
|
|
}
|
|
|
|
if (braceEscaped === true || code === CHAR_LEFT_CURLY_BRACE) {
|
|
braces++;
|
|
|
|
while (eos() !== true && (code = advance())) {
|
|
if (code === CHAR_BACKWARD_SLASH) {
|
|
backslashes = token.backslashes = true;
|
|
advance();
|
|
continue;
|
|
}
|
|
|
|
if (code === CHAR_LEFT_CURLY_BRACE) {
|
|
braces++;
|
|
continue;
|
|
}
|
|
|
|
if (braceEscaped !== true && code === CHAR_DOT && (code = advance()) === CHAR_DOT) {
|
|
isBrace = token.isBrace = true;
|
|
isGlob = token.isGlob = true;
|
|
finished = true;
|
|
|
|
if (scanToEnd === true) {
|
|
continue;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
if (braceEscaped !== true && code === CHAR_COMMA) {
|
|
isBrace = token.isBrace = true;
|
|
isGlob = token.isGlob = true;
|
|
finished = true;
|
|
|
|
if (scanToEnd === true) {
|
|
continue;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
if (code === CHAR_RIGHT_CURLY_BRACE) {
|
|
braces--;
|
|
|
|
if (braces === 0) {
|
|
braceEscaped = false;
|
|
isBrace = token.isBrace = true;
|
|
finished = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (scanToEnd === true) {
|
|
continue;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
if (code === CHAR_FORWARD_SLASH) {
|
|
slashes.push(index);
|
|
tokens.push(token);
|
|
token = { value: '', depth: 0, isGlob: false };
|
|
|
|
if (finished === true) continue;
|
|
if (prev === CHAR_DOT && index === (start + 1)) {
|
|
start += 2;
|
|
continue;
|
|
}
|
|
|
|
lastIndex = index + 1;
|
|
continue;
|
|
}
|
|
|
|
if (opts.noext !== true) {
|
|
const isExtglobChar = code === CHAR_PLUS
|
|
|| code === CHAR_AT
|
|
|| code === CHAR_ASTERISK
|
|
|| code === CHAR_QUESTION_MARK
|
|
|| code === CHAR_EXCLAMATION_MARK;
|
|
|
|
if (isExtglobChar === true && peek() === CHAR_LEFT_PARENTHESES) {
|
|
isGlob = token.isGlob = true;
|
|
isExtglob = token.isExtglob = true;
|
|
finished = true;
|
|
if (code === CHAR_EXCLAMATION_MARK && index === start) {
|
|
negatedExtglob = true;
|
|
}
|
|
|
|
if (scanToEnd === true) {
|
|
while (eos() !== true && (code = advance())) {
|
|
if (code === CHAR_BACKWARD_SLASH) {
|
|
backslashes = token.backslashes = true;
|
|
code = advance();
|
|
continue;
|
|
}
|
|
|
|
if (code === CHAR_RIGHT_PARENTHESES) {
|
|
isGlob = token.isGlob = true;
|
|
finished = true;
|
|
break;
|
|
}
|
|
}
|
|
continue;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (code === CHAR_ASTERISK) {
|
|
if (prev === CHAR_ASTERISK) isGlobstar = token.isGlobstar = true;
|
|
isGlob = token.isGlob = true;
|
|
finished = true;
|
|
|
|
if (scanToEnd === true) {
|
|
continue;
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (code === CHAR_QUESTION_MARK) {
|
|
isGlob = token.isGlob = true;
|
|
finished = true;
|
|
|
|
if (scanToEnd === true) {
|
|
continue;
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (code === CHAR_LEFT_SQUARE_BRACKET) {
|
|
while (eos() !== true && (next = advance())) {
|
|
if (next === CHAR_BACKWARD_SLASH) {
|
|
backslashes = token.backslashes = true;
|
|
advance();
|
|
continue;
|
|
}
|
|
|
|
if (next === CHAR_RIGHT_SQUARE_BRACKET) {
|
|
isBracket = token.isBracket = true;
|
|
isGlob = token.isGlob = true;
|
|
finished = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (scanToEnd === true) {
|
|
continue;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
if (opts.nonegate !== true && code === CHAR_EXCLAMATION_MARK && index === start) {
|
|
negated = token.negated = true;
|
|
start++;
|
|
continue;
|
|
}
|
|
|
|
if (opts.noparen !== true && code === CHAR_LEFT_PARENTHESES) {
|
|
isGlob = token.isGlob = true;
|
|
|
|
if (scanToEnd === true) {
|
|
while (eos() !== true && (code = advance())) {
|
|
if (code === CHAR_LEFT_PARENTHESES) {
|
|
backslashes = token.backslashes = true;
|
|
code = advance();
|
|
continue;
|
|
}
|
|
|
|
if (code === CHAR_RIGHT_PARENTHESES) {
|
|
finished = true;
|
|
break;
|
|
}
|
|
}
|
|
continue;
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (isGlob === true) {
|
|
finished = true;
|
|
|
|
if (scanToEnd === true) {
|
|
continue;
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (opts.noext === true) {
|
|
isExtglob = false;
|
|
isGlob = false;
|
|
}
|
|
|
|
let base = str;
|
|
let prefix = '';
|
|
let glob = '';
|
|
|
|
if (start > 0) {
|
|
prefix = str.slice(0, start);
|
|
str = str.slice(start);
|
|
lastIndex -= start;
|
|
}
|
|
|
|
if (base && isGlob === true && lastIndex > 0) {
|
|
base = str.slice(0, lastIndex);
|
|
glob = str.slice(lastIndex);
|
|
} else if (isGlob === true) {
|
|
base = '';
|
|
glob = str;
|
|
} else {
|
|
base = str;
|
|
}
|
|
|
|
if (base && base !== '' && base !== '/' && base !== str) {
|
|
if (isPathSeparator(base.charCodeAt(base.length - 1))) {
|
|
base = base.slice(0, -1);
|
|
}
|
|
}
|
|
|
|
if (opts.unescape === true) {
|
|
if (glob) glob = utils$2.removeBackslashes(glob);
|
|
|
|
if (base && backslashes === true) {
|
|
base = utils$2.removeBackslashes(base);
|
|
}
|
|
}
|
|
|
|
const state = {
|
|
prefix,
|
|
input,
|
|
start,
|
|
base,
|
|
glob,
|
|
isBrace,
|
|
isBracket,
|
|
isGlob,
|
|
isExtglob,
|
|
isGlobstar,
|
|
negated,
|
|
negatedExtglob
|
|
};
|
|
|
|
if (opts.tokens === true) {
|
|
state.maxDepth = 0;
|
|
if (!isPathSeparator(code)) {
|
|
tokens.push(token);
|
|
}
|
|
state.tokens = tokens;
|
|
}
|
|
|
|
if (opts.parts === true || opts.tokens === true) {
|
|
let prevIndex;
|
|
|
|
for (let idx = 0; idx < slashes.length; idx++) {
|
|
const n = prevIndex ? prevIndex + 1 : start;
|
|
const i = slashes[idx];
|
|
const value = input.slice(n, i);
|
|
if (opts.tokens) {
|
|
if (idx === 0 && start !== 0) {
|
|
tokens[idx].isPrefix = true;
|
|
tokens[idx].value = prefix;
|
|
} else {
|
|
tokens[idx].value = value;
|
|
}
|
|
depth(tokens[idx]);
|
|
state.maxDepth += tokens[idx].depth;
|
|
}
|
|
if (idx !== 0 || value !== '') {
|
|
parts.push(value);
|
|
}
|
|
prevIndex = i;
|
|
}
|
|
|
|
if (prevIndex && prevIndex + 1 < input.length) {
|
|
const value = input.slice(prevIndex + 1);
|
|
parts.push(value);
|
|
|
|
if (opts.tokens) {
|
|
tokens[tokens.length - 1].value = value;
|
|
depth(tokens[tokens.length - 1]);
|
|
state.maxDepth += tokens[tokens.length - 1].depth;
|
|
}
|
|
}
|
|
|
|
state.slashes = slashes;
|
|
state.parts = parts;
|
|
}
|
|
|
|
return state;
|
|
};
|
|
|
|
var scan_1 = scan$1;
|
|
|
|
const constants$1 = constants$2;
|
|
const utils$1 = utils$3;
|
|
|
|
/**
|
|
* Constants
|
|
*/
|
|
|
|
const {
|
|
MAX_LENGTH,
|
|
POSIX_REGEX_SOURCE,
|
|
REGEX_NON_SPECIAL_CHARS,
|
|
REGEX_SPECIAL_CHARS_BACKREF,
|
|
REPLACEMENTS
|
|
} = constants$1;
|
|
|
|
/**
|
|
* Helpers
|
|
*/
|
|
|
|
const expandRange = (args, options) => {
|
|
if (typeof options.expandRange === 'function') {
|
|
return options.expandRange(...args, options);
|
|
}
|
|
|
|
args.sort();
|
|
const value = `[${args.join('-')}]`;
|
|
|
|
return value;
|
|
};
|
|
|
|
/**
|
|
* Create the message for a syntax error
|
|
*/
|
|
|
|
const syntaxError = (type, char) => {
|
|
return `Missing ${type}: "${char}" - use "\\\\${char}" to match literal characters`;
|
|
};
|
|
|
|
/**
|
|
* Parse the given input string.
|
|
* @param {String} input
|
|
* @param {Object} options
|
|
* @return {Object}
|
|
*/
|
|
|
|
const parse$2 = (input, options) => {
|
|
if (typeof input !== 'string') {
|
|
throw new TypeError('Expected a string');
|
|
}
|
|
|
|
input = REPLACEMENTS[input] || input;
|
|
|
|
const opts = { ...options };
|
|
const max = typeof opts.maxLength === 'number' ? Math.min(MAX_LENGTH, opts.maxLength) : MAX_LENGTH;
|
|
|
|
let len = input.length;
|
|
if (len > max) {
|
|
throw new SyntaxError(`Input length: ${len}, exceeds maximum allowed length: ${max}`);
|
|
}
|
|
|
|
const bos = { type: 'bos', value: '', output: opts.prepend || '' };
|
|
const tokens = [bos];
|
|
|
|
const capture = opts.capture ? '' : '?:';
|
|
const win32 = utils$1.isWindows(options);
|
|
|
|
// create constants based on platform, for windows or posix
|
|
const PLATFORM_CHARS = constants$1.globChars(win32);
|
|
const EXTGLOB_CHARS = constants$1.extglobChars(PLATFORM_CHARS);
|
|
|
|
const {
|
|
DOT_LITERAL,
|
|
PLUS_LITERAL,
|
|
SLASH_LITERAL,
|
|
ONE_CHAR,
|
|
DOTS_SLASH,
|
|
NO_DOT,
|
|
NO_DOT_SLASH,
|
|
NO_DOTS_SLASH,
|
|
QMARK,
|
|
QMARK_NO_DOT,
|
|
STAR,
|
|
START_ANCHOR
|
|
} = PLATFORM_CHARS;
|
|
|
|
const globstar = opts => {
|
|
return `(${capture}(?:(?!${START_ANCHOR}${opts.dot ? DOTS_SLASH : DOT_LITERAL}).)*?)`;
|
|
};
|
|
|
|
const nodot = opts.dot ? '' : NO_DOT;
|
|
const qmarkNoDot = opts.dot ? QMARK : QMARK_NO_DOT;
|
|
let star = opts.bash === true ? globstar(opts) : STAR;
|
|
|
|
if (opts.capture) {
|
|
star = `(${star})`;
|
|
}
|
|
|
|
// minimatch options support
|
|
if (typeof opts.noext === 'boolean') {
|
|
opts.noextglob = opts.noext;
|
|
}
|
|
|
|
const state = {
|
|
input,
|
|
index: -1,
|
|
start: 0,
|
|
dot: opts.dot === true,
|
|
consumed: '',
|
|
output: '',
|
|
prefix: '',
|
|
backtrack: false,
|
|
negated: false,
|
|
brackets: 0,
|
|
braces: 0,
|
|
parens: 0,
|
|
quotes: 0,
|
|
globstar: false,
|
|
tokens
|
|
};
|
|
|
|
input = utils$1.removePrefix(input, state);
|
|
len = input.length;
|
|
|
|
const extglobs = [];
|
|
const braces = [];
|
|
const stack = [];
|
|
let prev = bos;
|
|
let value;
|
|
|
|
/**
|
|
* Tokenizing helpers
|
|
*/
|
|
|
|
const eos = () => state.index === len - 1;
|
|
const peek = state.peek = (n = 1) => input[state.index + n];
|
|
const advance = state.advance = () => input[++state.index] || '';
|
|
const remaining = () => input.slice(state.index + 1);
|
|
const consume = (value = '', num = 0) => {
|
|
state.consumed += value;
|
|
state.index += num;
|
|
};
|
|
|
|
const append = token => {
|
|
state.output += token.output != null ? token.output : token.value;
|
|
consume(token.value);
|
|
};
|
|
|
|
const negate = () => {
|
|
let count = 1;
|
|
|
|
while (peek() === '!' && (peek(2) !== '(' || peek(3) === '?')) {
|
|
advance();
|
|
state.start++;
|
|
count++;
|
|
}
|
|
|
|
if (count % 2 === 0) {
|
|
return false;
|
|
}
|
|
|
|
state.negated = true;
|
|
state.start++;
|
|
return true;
|
|
};
|
|
|
|
const increment = type => {
|
|
state[type]++;
|
|
stack.push(type);
|
|
};
|
|
|
|
const decrement = type => {
|
|
state[type]--;
|
|
stack.pop();
|
|
};
|
|
|
|
/**
|
|
* Push tokens onto the tokens array. This helper speeds up
|
|
* tokenizing by 1) helping us avoid backtracking as much as possible,
|
|
* and 2) helping us avoid creating extra tokens when consecutive
|
|
* characters are plain text. This improves performance and simplifies
|
|
* lookbehinds.
|
|
*/
|
|
|
|
const push = tok => {
|
|
if (prev.type === 'globstar') {
|
|
const isBrace = state.braces > 0 && (tok.type === 'comma' || tok.type === 'brace');
|
|
const isExtglob = tok.extglob === true || (extglobs.length && (tok.type === 'pipe' || tok.type === 'paren'));
|
|
|
|
if (tok.type !== 'slash' && tok.type !== 'paren' && !isBrace && !isExtglob) {
|
|
state.output = state.output.slice(0, -prev.output.length);
|
|
prev.type = 'star';
|
|
prev.value = '*';
|
|
prev.output = star;
|
|
state.output += prev.output;
|
|
}
|
|
}
|
|
|
|
if (extglobs.length && tok.type !== 'paren') {
|
|
extglobs[extglobs.length - 1].inner += tok.value;
|
|
}
|
|
|
|
if (tok.value || tok.output) append(tok);
|
|
if (prev && prev.type === 'text' && tok.type === 'text') {
|
|
prev.value += tok.value;
|
|
prev.output = (prev.output || '') + tok.value;
|
|
return;
|
|
}
|
|
|
|
tok.prev = prev;
|
|
tokens.push(tok);
|
|
prev = tok;
|
|
};
|
|
|
|
const extglobOpen = (type, value) => {
|
|
const token = { ...EXTGLOB_CHARS[value], conditions: 1, inner: '' };
|
|
|
|
token.prev = prev;
|
|
token.parens = state.parens;
|
|
token.output = state.output;
|
|
const output = (opts.capture ? '(' : '') + token.open;
|
|
|
|
increment('parens');
|
|
push({ type, value, output: state.output ? '' : ONE_CHAR });
|
|
push({ type: 'paren', extglob: true, value: advance(), output });
|
|
extglobs.push(token);
|
|
};
|
|
|
|
const extglobClose = token => {
|
|
let output = token.close + (opts.capture ? ')' : '');
|
|
let rest;
|
|
|
|
if (token.type === 'negate') {
|
|
let extglobStar = star;
|
|
|
|
if (token.inner && token.inner.length > 1 && token.inner.includes('/')) {
|
|
extglobStar = globstar(opts);
|
|
}
|
|
|
|
if (extglobStar !== star || eos() || /^\)+$/.test(remaining())) {
|
|
output = token.close = `)$))${extglobStar}`;
|
|
}
|
|
|
|
if (token.inner.includes('*') && (rest = remaining()) && /^\.[^\\/.]+$/.test(rest)) {
|
|
// Any non-magical string (`.ts`) or even nested expression (`.{ts,tsx}`) can follow after the closing parenthesis.
|
|
// In this case, we need to parse the string and use it in the output of the original pattern.
|
|
// Suitable patterns: `/!(*.d).ts`, `/!(*.d).{ts,tsx}`, `**/!(*-dbg).@(js)`.
|
|
//
|
|
// Disabling the `fastpaths` option due to a problem with parsing strings as `.ts` in the pattern like `**/!(*.d).ts`.
|
|
const expression = parse$2(rest, { ...options, fastpaths: false }).output;
|
|
|
|
output = token.close = `)${expression})${extglobStar})`;
|
|
}
|
|
|
|
if (token.prev.type === 'bos') {
|
|
state.negatedExtglob = true;
|
|
}
|
|
}
|
|
|
|
push({ type: 'paren', extglob: true, value, output });
|
|
decrement('parens');
|
|
};
|
|
|
|
/**
|
|
* Fast paths
|
|
*/
|
|
|
|
if (opts.fastpaths !== false && !/(^[*!]|[/()[\]{}"])/.test(input)) {
|
|
let backslashes = false;
|
|
|
|
let output = input.replace(REGEX_SPECIAL_CHARS_BACKREF, (m, esc, chars, first, rest, index) => {
|
|
if (first === '\\') {
|
|
backslashes = true;
|
|
return m;
|
|
}
|
|
|
|
if (first === '?') {
|
|
if (esc) {
|
|
return esc + first + (rest ? QMARK.repeat(rest.length) : '');
|
|
}
|
|
if (index === 0) {
|
|
return qmarkNoDot + (rest ? QMARK.repeat(rest.length) : '');
|
|
}
|
|
return QMARK.repeat(chars.length);
|
|
}
|
|
|
|
if (first === '.') {
|
|
return DOT_LITERAL.repeat(chars.length);
|
|
}
|
|
|
|
if (first === '*') {
|
|
if (esc) {
|
|
return esc + first + (rest ? star : '');
|
|
}
|
|
return star;
|
|
}
|
|
return esc ? m : `\\${m}`;
|
|
});
|
|
|
|
if (backslashes === true) {
|
|
if (opts.unescape === true) {
|
|
output = output.replace(/\\/g, '');
|
|
} else {
|
|
output = output.replace(/\\+/g, m => {
|
|
return m.length % 2 === 0 ? '\\\\' : (m ? '\\' : '');
|
|
});
|
|
}
|
|
}
|
|
|
|
if (output === input && opts.contains === true) {
|
|
state.output = input;
|
|
return state;
|
|
}
|
|
|
|
state.output = utils$1.wrapOutput(output, state, options);
|
|
return state;
|
|
}
|
|
|
|
/**
|
|
* Tokenize input until we reach end-of-string
|
|
*/
|
|
|
|
while (!eos()) {
|
|
value = advance();
|
|
|
|
if (value === '\u0000') {
|
|
continue;
|
|
}
|
|
|
|
/**
|
|
* Escaped characters
|
|
*/
|
|
|
|
if (value === '\\') {
|
|
const next = peek();
|
|
|
|
if (next === '/' && opts.bash !== true) {
|
|
continue;
|
|
}
|
|
|
|
if (next === '.' || next === ';') {
|
|
continue;
|
|
}
|
|
|
|
if (!next) {
|
|
value += '\\';
|
|
push({ type: 'text', value });
|
|
continue;
|
|
}
|
|
|
|
// collapse slashes to reduce potential for exploits
|
|
const match = /^\\+/.exec(remaining());
|
|
let slashes = 0;
|
|
|
|
if (match && match[0].length > 2) {
|
|
slashes = match[0].length;
|
|
state.index += slashes;
|
|
if (slashes % 2 !== 0) {
|
|
value += '\\';
|
|
}
|
|
}
|
|
|
|
if (opts.unescape === true) {
|
|
value = advance();
|
|
} else {
|
|
value += advance();
|
|
}
|
|
|
|
if (state.brackets === 0) {
|
|
push({ type: 'text', value });
|
|
continue;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* If we're inside a regex character class, continue
|
|
* until we reach the closing bracket.
|
|
*/
|
|
|
|
if (state.brackets > 0 && (value !== ']' || prev.value === '[' || prev.value === '[^')) {
|
|
if (opts.posix !== false && value === ':') {
|
|
const inner = prev.value.slice(1);
|
|
if (inner.includes('[')) {
|
|
prev.posix = true;
|
|
|
|
if (inner.includes(':')) {
|
|
const idx = prev.value.lastIndexOf('[');
|
|
const pre = prev.value.slice(0, idx);
|
|
const rest = prev.value.slice(idx + 2);
|
|
const posix = POSIX_REGEX_SOURCE[rest];
|
|
if (posix) {
|
|
prev.value = pre + posix;
|
|
state.backtrack = true;
|
|
advance();
|
|
|
|
if (!bos.output && tokens.indexOf(prev) === 1) {
|
|
bos.output = ONE_CHAR;
|
|
}
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if ((value === '[' && peek() !== ':') || (value === '-' && peek() === ']')) {
|
|
value = `\\${value}`;
|
|
}
|
|
|
|
if (value === ']' && (prev.value === '[' || prev.value === '[^')) {
|
|
value = `\\${value}`;
|
|
}
|
|
|
|
if (opts.posix === true && value === '!' && prev.value === '[') {
|
|
value = '^';
|
|
}
|
|
|
|
prev.value += value;
|
|
append({ value });
|
|
continue;
|
|
}
|
|
|
|
/**
|
|
* If we're inside a quoted string, continue
|
|
* until we reach the closing double quote.
|
|
*/
|
|
|
|
if (state.quotes === 1 && value !== '"') {
|
|
value = utils$1.escapeRegex(value);
|
|
prev.value += value;
|
|
append({ value });
|
|
continue;
|
|
}
|
|
|
|
/**
|
|
* Double quotes
|
|
*/
|
|
|
|
if (value === '"') {
|
|
state.quotes = state.quotes === 1 ? 0 : 1;
|
|
if (opts.keepQuotes === true) {
|
|
push({ type: 'text', value });
|
|
}
|
|
continue;
|
|
}
|
|
|
|
/**
|
|
* Parentheses
|
|
*/
|
|
|
|
if (value === '(') {
|
|
increment('parens');
|
|
push({ type: 'paren', value });
|
|
continue;
|
|
}
|
|
|
|
if (value === ')') {
|
|
if (state.parens === 0 && opts.strictBrackets === true) {
|
|
throw new SyntaxError(syntaxError('opening', '('));
|
|
}
|
|
|
|
const extglob = extglobs[extglobs.length - 1];
|
|
if (extglob && state.parens === extglob.parens + 1) {
|
|
extglobClose(extglobs.pop());
|
|
continue;
|
|
}
|
|
|
|
push({ type: 'paren', value, output: state.parens ? ')' : '\\)' });
|
|
decrement('parens');
|
|
continue;
|
|
}
|
|
|
|
/**
|
|
* Square brackets
|
|
*/
|
|
|
|
if (value === '[') {
|
|
if (opts.nobracket === true || !remaining().includes(']')) {
|
|
if (opts.nobracket !== true && opts.strictBrackets === true) {
|
|
throw new SyntaxError(syntaxError('closing', ']'));
|
|
}
|
|
|
|
value = `\\${value}`;
|
|
} else {
|
|
increment('brackets');
|
|
}
|
|
|
|
push({ type: 'bracket', value });
|
|
continue;
|
|
}
|
|
|
|
if (value === ']') {
|
|
if (opts.nobracket === true || (prev && prev.type === 'bracket' && prev.value.length === 1)) {
|
|
push({ type: 'text', value, output: `\\${value}` });
|
|
continue;
|
|
}
|
|
|
|
if (state.brackets === 0) {
|
|
if (opts.strictBrackets === true) {
|
|
throw new SyntaxError(syntaxError('opening', '['));
|
|
}
|
|
|
|
push({ type: 'text', value, output: `\\${value}` });
|
|
continue;
|
|
}
|
|
|
|
decrement('brackets');
|
|
|
|
const prevValue = prev.value.slice(1);
|
|
if (prev.posix !== true && prevValue[0] === '^' && !prevValue.includes('/')) {
|
|
value = `/${value}`;
|
|
}
|
|
|
|
prev.value += value;
|
|
append({ value });
|
|
|
|
// when literal brackets are explicitly disabled
|
|
// assume we should match with a regex character class
|
|
if (opts.literalBrackets === false || utils$1.hasRegexChars(prevValue)) {
|
|
continue;
|
|
}
|
|
|
|
const escaped = utils$1.escapeRegex(prev.value);
|
|
state.output = state.output.slice(0, -prev.value.length);
|
|
|
|
// when literal brackets are explicitly enabled
|
|
// assume we should escape the brackets to match literal characters
|
|
if (opts.literalBrackets === true) {
|
|
state.output += escaped;
|
|
prev.value = escaped;
|
|
continue;
|
|
}
|
|
|
|
// when the user specifies nothing, try to match both
|
|
prev.value = `(${capture}${escaped}|${prev.value})`;
|
|
state.output += prev.value;
|
|
continue;
|
|
}
|
|
|
|
/**
|
|
* Braces
|
|
*/
|
|
|
|
if (value === '{' && opts.nobrace !== true) {
|
|
increment('braces');
|
|
|
|
const open = {
|
|
type: 'brace',
|
|
value,
|
|
output: '(',
|
|
outputIndex: state.output.length,
|
|
tokensIndex: state.tokens.length
|
|
};
|
|
|
|
braces.push(open);
|
|
push(open);
|
|
continue;
|
|
}
|
|
|
|
if (value === '}') {
|
|
const brace = braces[braces.length - 1];
|
|
|
|
if (opts.nobrace === true || !brace) {
|
|
push({ type: 'text', value, output: value });
|
|
continue;
|
|
}
|
|
|
|
let output = ')';
|
|
|
|
if (brace.dots === true) {
|
|
const arr = tokens.slice();
|
|
const range = [];
|
|
|
|
for (let i = arr.length - 1; i >= 0; i--) {
|
|
tokens.pop();
|
|
if (arr[i].type === 'brace') {
|
|
break;
|
|
}
|
|
if (arr[i].type !== 'dots') {
|
|
range.unshift(arr[i].value);
|
|
}
|
|
}
|
|
|
|
output = expandRange(range, opts);
|
|
state.backtrack = true;
|
|
}
|
|
|
|
if (brace.comma !== true && brace.dots !== true) {
|
|
const out = state.output.slice(0, brace.outputIndex);
|
|
const toks = state.tokens.slice(brace.tokensIndex);
|
|
brace.value = brace.output = '\\{';
|
|
value = output = '\\}';
|
|
state.output = out;
|
|
for (const t of toks) {
|
|
state.output += (t.output || t.value);
|
|
}
|
|
}
|
|
|
|
push({ type: 'brace', value, output });
|
|
decrement('braces');
|
|
braces.pop();
|
|
continue;
|
|
}
|
|
|
|
/**
|
|
* Pipes
|
|
*/
|
|
|
|
if (value === '|') {
|
|
if (extglobs.length > 0) {
|
|
extglobs[extglobs.length - 1].conditions++;
|
|
}
|
|
push({ type: 'text', value });
|
|
continue;
|
|
}
|
|
|
|
/**
|
|
* Commas
|
|
*/
|
|
|
|
if (value === ',') {
|
|
let output = value;
|
|
|
|
const brace = braces[braces.length - 1];
|
|
if (brace && stack[stack.length - 1] === 'braces') {
|
|
brace.comma = true;
|
|
output = '|';
|
|
}
|
|
|
|
push({ type: 'comma', value, output });
|
|
continue;
|
|
}
|
|
|
|
/**
|
|
* Slashes
|
|
*/
|
|
|
|
if (value === '/') {
|
|
// if the beginning of the glob is "./", advance the start
|
|
// to the current index, and don't add the "./" characters
|
|
// to the state. This greatly simplifies lookbehinds when
|
|
// checking for BOS characters like "!" and "." (not "./")
|
|
if (prev.type === 'dot' && state.index === state.start + 1) {
|
|
state.start = state.index + 1;
|
|
state.consumed = '';
|
|
state.output = '';
|
|
tokens.pop();
|
|
prev = bos; // reset "prev" to the first token
|
|
continue;
|
|
}
|
|
|
|
push({ type: 'slash', value, output: SLASH_LITERAL });
|
|
continue;
|
|
}
|
|
|
|
/**
|
|
* Dots
|
|
*/
|
|
|
|
if (value === '.') {
|
|
if (state.braces > 0 && prev.type === 'dot') {
|
|
if (prev.value === '.') prev.output = DOT_LITERAL;
|
|
const brace = braces[braces.length - 1];
|
|
prev.type = 'dots';
|
|
prev.output += value;
|
|
prev.value += value;
|
|
brace.dots = true;
|
|
continue;
|
|
}
|
|
|
|
if ((state.braces + state.parens) === 0 && prev.type !== 'bos' && prev.type !== 'slash') {
|
|
push({ type: 'text', value, output: DOT_LITERAL });
|
|
continue;
|
|
}
|
|
|
|
push({ type: 'dot', value, output: DOT_LITERAL });
|
|
continue;
|
|
}
|
|
|
|
/**
|
|
* Question marks
|
|
*/
|
|
|
|
if (value === '?') {
|
|
const isGroup = prev && prev.value === '(';
|
|
if (!isGroup && opts.noextglob !== true && peek() === '(' && peek(2) !== '?') {
|
|
extglobOpen('qmark', value);
|
|
continue;
|
|
}
|
|
|
|
if (prev && prev.type === 'paren') {
|
|
const next = peek();
|
|
let output = value;
|
|
|
|
if (next === '<' && !utils$1.supportsLookbehinds()) {
|
|
throw new Error('Node.js v10 or higher is required for regex lookbehinds');
|
|
}
|
|
|
|
if ((prev.value === '(' && !/[!=<:]/.test(next)) || (next === '<' && !/<([!=]|\w+>)/.test(remaining()))) {
|
|
output = `\\${value}`;
|
|
}
|
|
|
|
push({ type: 'text', value, output });
|
|
continue;
|
|
}
|
|
|
|
if (opts.dot !== true && (prev.type === 'slash' || prev.type === 'bos')) {
|
|
push({ type: 'qmark', value, output: QMARK_NO_DOT });
|
|
continue;
|
|
}
|
|
|
|
push({ type: 'qmark', value, output: QMARK });
|
|
continue;
|
|
}
|
|
|
|
/**
|
|
* Exclamation
|
|
*/
|
|
|
|
if (value === '!') {
|
|
if (opts.noextglob !== true && peek() === '(') {
|
|
if (peek(2) !== '?' || !/[!=<:]/.test(peek(3))) {
|
|
extglobOpen('negate', value);
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if (opts.nonegate !== true && state.index === 0) {
|
|
negate();
|
|
continue;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Plus
|
|
*/
|
|
|
|
if (value === '+') {
|
|
if (opts.noextglob !== true && peek() === '(' && peek(2) !== '?') {
|
|
extglobOpen('plus', value);
|
|
continue;
|
|
}
|
|
|
|
if ((prev && prev.value === '(') || opts.regex === false) {
|
|
push({ type: 'plus', value, output: PLUS_LITERAL });
|
|
continue;
|
|
}
|
|
|
|
if ((prev && (prev.type === 'bracket' || prev.type === 'paren' || prev.type === 'brace')) || state.parens > 0) {
|
|
push({ type: 'plus', value });
|
|
continue;
|
|
}
|
|
|
|
push({ type: 'plus', value: PLUS_LITERAL });
|
|
continue;
|
|
}
|
|
|
|
/**
|
|
* Plain text
|
|
*/
|
|
|
|
if (value === '@') {
|
|
if (opts.noextglob !== true && peek() === '(' && peek(2) !== '?') {
|
|
push({ type: 'at', extglob: true, value, output: '' });
|
|
continue;
|
|
}
|
|
|
|
push({ type: 'text', value });
|
|
continue;
|
|
}
|
|
|
|
/**
|
|
* Plain text
|
|
*/
|
|
|
|
if (value !== '*') {
|
|
if (value === '$' || value === '^') {
|
|
value = `\\${value}`;
|
|
}
|
|
|
|
const match = REGEX_NON_SPECIAL_CHARS.exec(remaining());
|
|
if (match) {
|
|
value += match[0];
|
|
state.index += match[0].length;
|
|
}
|
|
|
|
push({ type: 'text', value });
|
|
continue;
|
|
}
|
|
|
|
/**
|
|
* Stars
|
|
*/
|
|
|
|
if (prev && (prev.type === 'globstar' || prev.star === true)) {
|
|
prev.type = 'star';
|
|
prev.star = true;
|
|
prev.value += value;
|
|
prev.output = star;
|
|
state.backtrack = true;
|
|
state.globstar = true;
|
|
consume(value);
|
|
continue;
|
|
}
|
|
|
|
let rest = remaining();
|
|
if (opts.noextglob !== true && /^\([^?]/.test(rest)) {
|
|
extglobOpen('star', value);
|
|
continue;
|
|
}
|
|
|
|
if (prev.type === 'star') {
|
|
if (opts.noglobstar === true) {
|
|
consume(value);
|
|
continue;
|
|
}
|
|
|
|
const prior = prev.prev;
|
|
const before = prior.prev;
|
|
const isStart = prior.type === 'slash' || prior.type === 'bos';
|
|
const afterStar = before && (before.type === 'star' || before.type === 'globstar');
|
|
|
|
if (opts.bash === true && (!isStart || (rest[0] && rest[0] !== '/'))) {
|
|
push({ type: 'star', value, output: '' });
|
|
continue;
|
|
}
|
|
|
|
const isBrace = state.braces > 0 && (prior.type === 'comma' || prior.type === 'brace');
|
|
const isExtglob = extglobs.length && (prior.type === 'pipe' || prior.type === 'paren');
|
|
if (!isStart && prior.type !== 'paren' && !isBrace && !isExtglob) {
|
|
push({ type: 'star', value, output: '' });
|
|
continue;
|
|
}
|
|
|
|
// strip consecutive `/**/`
|
|
while (rest.slice(0, 3) === '/**') {
|
|
const after = input[state.index + 4];
|
|
if (after && after !== '/') {
|
|
break;
|
|
}
|
|
rest = rest.slice(3);
|
|
consume('/**', 3);
|
|
}
|
|
|
|
if (prior.type === 'bos' && eos()) {
|
|
prev.type = 'globstar';
|
|
prev.value += value;
|
|
prev.output = globstar(opts);
|
|
state.output = prev.output;
|
|
state.globstar = true;
|
|
consume(value);
|
|
continue;
|
|
}
|
|
|
|
if (prior.type === 'slash' && prior.prev.type !== 'bos' && !afterStar && eos()) {
|
|
state.output = state.output.slice(0, -(prior.output + prev.output).length);
|
|
prior.output = `(?:${prior.output}`;
|
|
|
|
prev.type = 'globstar';
|
|
prev.output = globstar(opts) + (opts.strictSlashes ? ')' : '|$)');
|
|
prev.value += value;
|
|
state.globstar = true;
|
|
state.output += prior.output + prev.output;
|
|
consume(value);
|
|
continue;
|
|
}
|
|
|
|
if (prior.type === 'slash' && prior.prev.type !== 'bos' && rest[0] === '/') {
|
|
const end = rest[1] !== void 0 ? '|$' : '';
|
|
|
|
state.output = state.output.slice(0, -(prior.output + prev.output).length);
|
|
prior.output = `(?:${prior.output}`;
|
|
|
|
prev.type = 'globstar';
|
|
prev.output = `${globstar(opts)}${SLASH_LITERAL}|${SLASH_LITERAL}${end})`;
|
|
prev.value += value;
|
|
|
|
state.output += prior.output + prev.output;
|
|
state.globstar = true;
|
|
|
|
consume(value + advance());
|
|
|
|
push({ type: 'slash', value: '/', output: '' });
|
|
continue;
|
|
}
|
|
|
|
if (prior.type === 'bos' && rest[0] === '/') {
|
|
prev.type = 'globstar';
|
|
prev.value += value;
|
|
prev.output = `(?:^|${SLASH_LITERAL}|${globstar(opts)}${SLASH_LITERAL})`;
|
|
state.output = prev.output;
|
|
state.globstar = true;
|
|
consume(value + advance());
|
|
push({ type: 'slash', value: '/', output: '' });
|
|
continue;
|
|
}
|
|
|
|
// remove single star from output
|
|
state.output = state.output.slice(0, -prev.output.length);
|
|
|
|
// reset previous token to globstar
|
|
prev.type = 'globstar';
|
|
prev.output = globstar(opts);
|
|
prev.value += value;
|
|
|
|
// reset output with globstar
|
|
state.output += prev.output;
|
|
state.globstar = true;
|
|
consume(value);
|
|
continue;
|
|
}
|
|
|
|
const token = { type: 'star', value, output: star };
|
|
|
|
if (opts.bash === true) {
|
|
token.output = '.*?';
|
|
if (prev.type === 'bos' || prev.type === 'slash') {
|
|
token.output = nodot + token.output;
|
|
}
|
|
push(token);
|
|
continue;
|
|
}
|
|
|
|
if (prev && (prev.type === 'bracket' || prev.type === 'paren') && opts.regex === true) {
|
|
token.output = value;
|
|
push(token);
|
|
continue;
|
|
}
|
|
|
|
if (state.index === state.start || prev.type === 'slash' || prev.type === 'dot') {
|
|
if (prev.type === 'dot') {
|
|
state.output += NO_DOT_SLASH;
|
|
prev.output += NO_DOT_SLASH;
|
|
|
|
} else if (opts.dot === true) {
|
|
state.output += NO_DOTS_SLASH;
|
|
prev.output += NO_DOTS_SLASH;
|
|
|
|
} else {
|
|
state.output += nodot;
|
|
prev.output += nodot;
|
|
}
|
|
|
|
if (peek() !== '*') {
|
|
state.output += ONE_CHAR;
|
|
prev.output += ONE_CHAR;
|
|
}
|
|
}
|
|
|
|
push(token);
|
|
}
|
|
|
|
while (state.brackets > 0) {
|
|
if (opts.strictBrackets === true) throw new SyntaxError(syntaxError('closing', ']'));
|
|
state.output = utils$1.escapeLast(state.output, '[');
|
|
decrement('brackets');
|
|
}
|
|
|
|
while (state.parens > 0) {
|
|
if (opts.strictBrackets === true) throw new SyntaxError(syntaxError('closing', ')'));
|
|
state.output = utils$1.escapeLast(state.output, '(');
|
|
decrement('parens');
|
|
}
|
|
|
|
while (state.braces > 0) {
|
|
if (opts.strictBrackets === true) throw new SyntaxError(syntaxError('closing', '}'));
|
|
state.output = utils$1.escapeLast(state.output, '{');
|
|
decrement('braces');
|
|
}
|
|
|
|
if (opts.strictSlashes !== true && (prev.type === 'star' || prev.type === 'bracket')) {
|
|
push({ type: 'maybe_slash', value: '', output: `${SLASH_LITERAL}?` });
|
|
}
|
|
|
|
// rebuild the output if we had to backtrack at any point
|
|
if (state.backtrack === true) {
|
|
state.output = '';
|
|
|
|
for (const token of state.tokens) {
|
|
state.output += token.output != null ? token.output : token.value;
|
|
|
|
if (token.suffix) {
|
|
state.output += token.suffix;
|
|
}
|
|
}
|
|
}
|
|
|
|
return state;
|
|
};
|
|
|
|
/**
|
|
* Fast paths for creating regular expressions for common glob patterns.
|
|
* This can significantly speed up processing and has very little downside
|
|
* impact when none of the fast paths match.
|
|
*/
|
|
|
|
parse$2.fastpaths = (input, options) => {
|
|
const opts = { ...options };
|
|
const max = typeof opts.maxLength === 'number' ? Math.min(MAX_LENGTH, opts.maxLength) : MAX_LENGTH;
|
|
const len = input.length;
|
|
if (len > max) {
|
|
throw new SyntaxError(`Input length: ${len}, exceeds maximum allowed length: ${max}`);
|
|
}
|
|
|
|
input = REPLACEMENTS[input] || input;
|
|
const win32 = utils$1.isWindows(options);
|
|
|
|
// create constants based on platform, for windows or posix
|
|
const {
|
|
DOT_LITERAL,
|
|
SLASH_LITERAL,
|
|
ONE_CHAR,
|
|
DOTS_SLASH,
|
|
NO_DOT,
|
|
NO_DOTS,
|
|
NO_DOTS_SLASH,
|
|
STAR,
|
|
START_ANCHOR
|
|
} = constants$1.globChars(win32);
|
|
|
|
const nodot = opts.dot ? NO_DOTS : NO_DOT;
|
|
const slashDot = opts.dot ? NO_DOTS_SLASH : NO_DOT;
|
|
const capture = opts.capture ? '' : '?:';
|
|
const state = { negated: false, prefix: '' };
|
|
let star = opts.bash === true ? '.*?' : STAR;
|
|
|
|
if (opts.capture) {
|
|
star = `(${star})`;
|
|
}
|
|
|
|
const globstar = opts => {
|
|
if (opts.noglobstar === true) return star;
|
|
return `(${capture}(?:(?!${START_ANCHOR}${opts.dot ? DOTS_SLASH : DOT_LITERAL}).)*?)`;
|
|
};
|
|
|
|
const create = str => {
|
|
switch (str) {
|
|
case '*':
|
|
return `${nodot}${ONE_CHAR}${star}`;
|
|
|
|
case '.*':
|
|
return `${DOT_LITERAL}${ONE_CHAR}${star}`;
|
|
|
|
case '*.*':
|
|
return `${nodot}${star}${DOT_LITERAL}${ONE_CHAR}${star}`;
|
|
|
|
case '*/*':
|
|
return `${nodot}${star}${SLASH_LITERAL}${ONE_CHAR}${slashDot}${star}`;
|
|
|
|
case '**':
|
|
return nodot + globstar(opts);
|
|
|
|
case '**/*':
|
|
return `(?:${nodot}${globstar(opts)}${SLASH_LITERAL})?${slashDot}${ONE_CHAR}${star}`;
|
|
|
|
case '**/*.*':
|
|
return `(?:${nodot}${globstar(opts)}${SLASH_LITERAL})?${slashDot}${star}${DOT_LITERAL}${ONE_CHAR}${star}`;
|
|
|
|
case '**/.*':
|
|
return `(?:${nodot}${globstar(opts)}${SLASH_LITERAL})?${DOT_LITERAL}${ONE_CHAR}${star}`;
|
|
|
|
default: {
|
|
const match = /^(.*?)\.(\w+)$/.exec(str);
|
|
if (!match) return;
|
|
|
|
const source = create(match[1]);
|
|
if (!source) return;
|
|
|
|
return source + DOT_LITERAL + match[2];
|
|
}
|
|
}
|
|
};
|
|
|
|
const output = utils$1.removePrefix(input, state);
|
|
let source = create(output);
|
|
|
|
if (source && opts.strictSlashes !== true) {
|
|
source += `${SLASH_LITERAL}?`;
|
|
}
|
|
|
|
return source;
|
|
};
|
|
|
|
var parse_1$1 = parse$2;
|
|
|
|
const path$1 = require$$0$1;
|
|
const scan = scan_1;
|
|
const parse$1 = parse_1$1;
|
|
const utils = utils$3;
|
|
const constants = constants$2;
|
|
const isObject$1 = val => val && typeof val === 'object' && !Array.isArray(val);
|
|
|
|
/**
|
|
* Creates a matcher function from one or more glob patterns. The
|
|
* returned function takes a string to match as its first argument,
|
|
* and returns true if the string is a match. The returned matcher
|
|
* function also takes a boolean as the second argument that, when true,
|
|
* returns an object with additional information.
|
|
*
|
|
* ```js
|
|
* const picomatch = require('picomatch');
|
|
* // picomatch(glob[, options]);
|
|
*
|
|
* const isMatch = picomatch('*.!(*a)');
|
|
* console.log(isMatch('a.a')); //=> false
|
|
* console.log(isMatch('a.b')); //=> true
|
|
* ```
|
|
* @name picomatch
|
|
* @param {String|Array} `globs` One or more glob patterns.
|
|
* @param {Object=} `options`
|
|
* @return {Function=} Returns a matcher function.
|
|
* @api public
|
|
*/
|
|
|
|
const picomatch$1 = (glob, options, returnState = false) => {
|
|
if (Array.isArray(glob)) {
|
|
const fns = glob.map(input => picomatch$1(input, options, returnState));
|
|
const arrayMatcher = str => {
|
|
for (const isMatch of fns) {
|
|
const state = isMatch(str);
|
|
if (state) return state;
|
|
}
|
|
return false;
|
|
};
|
|
return arrayMatcher;
|
|
}
|
|
|
|
const isState = isObject$1(glob) && glob.tokens && glob.input;
|
|
|
|
if (glob === '' || (typeof glob !== 'string' && !isState)) {
|
|
throw new TypeError('Expected pattern to be a non-empty string');
|
|
}
|
|
|
|
const opts = options || {};
|
|
const posix = utils.isWindows(options);
|
|
const regex = isState
|
|
? picomatch$1.compileRe(glob, options)
|
|
: picomatch$1.makeRe(glob, options, false, true);
|
|
|
|
const state = regex.state;
|
|
delete regex.state;
|
|
|
|
let isIgnored = () => false;
|
|
if (opts.ignore) {
|
|
const ignoreOpts = { ...options, ignore: null, onMatch: null, onResult: null };
|
|
isIgnored = picomatch$1(opts.ignore, ignoreOpts, returnState);
|
|
}
|
|
|
|
const matcher = (input, returnObject = false) => {
|
|
const { isMatch, match, output } = picomatch$1.test(input, regex, options, { glob, posix });
|
|
const result = { glob, state, regex, posix, input, output, match, isMatch };
|
|
|
|
if (typeof opts.onResult === 'function') {
|
|
opts.onResult(result);
|
|
}
|
|
|
|
if (isMatch === false) {
|
|
result.isMatch = false;
|
|
return returnObject ? result : false;
|
|
}
|
|
|
|
if (isIgnored(input)) {
|
|
if (typeof opts.onIgnore === 'function') {
|
|
opts.onIgnore(result);
|
|
}
|
|
result.isMatch = false;
|
|
return returnObject ? result : false;
|
|
}
|
|
|
|
if (typeof opts.onMatch === 'function') {
|
|
opts.onMatch(result);
|
|
}
|
|
return returnObject ? result : true;
|
|
};
|
|
|
|
if (returnState) {
|
|
matcher.state = state;
|
|
}
|
|
|
|
return matcher;
|
|
};
|
|
|
|
/**
|
|
* Test `input` with the given `regex`. This is used by the main
|
|
* `picomatch()` function to test the input string.
|
|
*
|
|
* ```js
|
|
* const picomatch = require('picomatch');
|
|
* // picomatch.test(input, regex[, options]);
|
|
*
|
|
* console.log(picomatch.test('foo/bar', /^(?:([^/]*?)\/([^/]*?))$/));
|
|
* // { isMatch: true, match: [ 'foo/', 'foo', 'bar' ], output: 'foo/bar' }
|
|
* ```
|
|
* @param {String} `input` String to test.
|
|
* @param {RegExp} `regex`
|
|
* @return {Object} Returns an object with matching info.
|
|
* @api public
|
|
*/
|
|
|
|
picomatch$1.test = (input, regex, options, { glob, posix } = {}) => {
|
|
if (typeof input !== 'string') {
|
|
throw new TypeError('Expected input to be a string');
|
|
}
|
|
|
|
if (input === '') {
|
|
return { isMatch: false, output: '' };
|
|
}
|
|
|
|
const opts = options || {};
|
|
const format = opts.format || (posix ? utils.toPosixSlashes : null);
|
|
let match = input === glob;
|
|
let output = (match && format) ? format(input) : input;
|
|
|
|
if (match === false) {
|
|
output = format ? format(input) : input;
|
|
match = output === glob;
|
|
}
|
|
|
|
if (match === false || opts.capture === true) {
|
|
if (opts.matchBase === true || opts.basename === true) {
|
|
match = picomatch$1.matchBase(input, regex, options, posix);
|
|
} else {
|
|
match = regex.exec(output);
|
|
}
|
|
}
|
|
|
|
return { isMatch: Boolean(match), match, output };
|
|
};
|
|
|
|
/**
|
|
* Match the basename of a filepath.
|
|
*
|
|
* ```js
|
|
* const picomatch = require('picomatch');
|
|
* // picomatch.matchBase(input, glob[, options]);
|
|
* console.log(picomatch.matchBase('foo/bar.js', '*.js'); // true
|
|
* ```
|
|
* @param {String} `input` String to test.
|
|
* @param {RegExp|String} `glob` Glob pattern or regex created by [.makeRe](#makeRe).
|
|
* @return {Boolean}
|
|
* @api public
|
|
*/
|
|
|
|
picomatch$1.matchBase = (input, glob, options, posix = utils.isWindows(options)) => {
|
|
const regex = glob instanceof RegExp ? glob : picomatch$1.makeRe(glob, options);
|
|
return regex.test(path$1.basename(input));
|
|
};
|
|
|
|
/**
|
|
* Returns true if **any** of the given glob `patterns` match the specified `string`.
|
|
*
|
|
* ```js
|
|
* const picomatch = require('picomatch');
|
|
* // picomatch.isMatch(string, patterns[, options]);
|
|
*
|
|
* console.log(picomatch.isMatch('a.a', ['b.*', '*.a'])); //=> true
|
|
* console.log(picomatch.isMatch('a.a', 'b.*')); //=> false
|
|
* ```
|
|
* @param {String|Array} str The string to test.
|
|
* @param {String|Array} patterns One or more glob patterns to use for matching.
|
|
* @param {Object} [options] See available [options](#options).
|
|
* @return {Boolean} Returns true if any patterns match `str`
|
|
* @api public
|
|
*/
|
|
|
|
picomatch$1.isMatch = (str, patterns, options) => picomatch$1(patterns, options)(str);
|
|
|
|
/**
|
|
* Parse a glob pattern to create the source string for a regular
|
|
* expression.
|
|
*
|
|
* ```js
|
|
* const picomatch = require('picomatch');
|
|
* const result = picomatch.parse(pattern[, options]);
|
|
* ```
|
|
* @param {String} `pattern`
|
|
* @param {Object} `options`
|
|
* @return {Object} Returns an object with useful properties and output to be used as a regex source string.
|
|
* @api public
|
|
*/
|
|
|
|
picomatch$1.parse = (pattern, options) => {
|
|
if (Array.isArray(pattern)) return pattern.map(p => picomatch$1.parse(p, options));
|
|
return parse$1(pattern, { ...options, fastpaths: false });
|
|
};
|
|
|
|
/**
|
|
* Scan a glob pattern to separate the pattern into segments.
|
|
*
|
|
* ```js
|
|
* const picomatch = require('picomatch');
|
|
* // picomatch.scan(input[, options]);
|
|
*
|
|
* const result = picomatch.scan('!./foo/*.js');
|
|
* console.log(result);
|
|
* { prefix: '!./',
|
|
* input: '!./foo/*.js',
|
|
* start: 3,
|
|
* base: 'foo',
|
|
* glob: '*.js',
|
|
* isBrace: false,
|
|
* isBracket: false,
|
|
* isGlob: true,
|
|
* isExtglob: false,
|
|
* isGlobstar: false,
|
|
* negated: true }
|
|
* ```
|
|
* @param {String} `input` Glob pattern to scan.
|
|
* @param {Object} `options`
|
|
* @return {Object} Returns an object with
|
|
* @api public
|
|
*/
|
|
|
|
picomatch$1.scan = (input, options) => scan(input, options);
|
|
|
|
/**
|
|
* Compile a regular expression from the `state` object returned by the
|
|
* [parse()](#parse) method.
|
|
*
|
|
* @param {Object} `state`
|
|
* @param {Object} `options`
|
|
* @param {Boolean} `returnOutput` Intended for implementors, this argument allows you to return the raw output from the parser.
|
|
* @param {Boolean} `returnState` Adds the state to a `state` property on the returned regex. Useful for implementors and debugging.
|
|
* @return {RegExp}
|
|
* @api public
|
|
*/
|
|
|
|
picomatch$1.compileRe = (state, options, returnOutput = false, returnState = false) => {
|
|
if (returnOutput === true) {
|
|
return state.output;
|
|
}
|
|
|
|
const opts = options || {};
|
|
const prepend = opts.contains ? '' : '^';
|
|
const append = opts.contains ? '' : '$';
|
|
|
|
let source = `${prepend}(?:${state.output})${append}`;
|
|
if (state && state.negated === true) {
|
|
source = `^(?!${source}).*$`;
|
|
}
|
|
|
|
const regex = picomatch$1.toRegex(source, options);
|
|
if (returnState === true) {
|
|
regex.state = state;
|
|
}
|
|
|
|
return regex;
|
|
};
|
|
|
|
/**
|
|
* Create a regular expression from a parsed glob pattern.
|
|
*
|
|
* ```js
|
|
* const picomatch = require('picomatch');
|
|
* const state = picomatch.parse('*.js');
|
|
* // picomatch.compileRe(state[, options]);
|
|
*
|
|
* console.log(picomatch.compileRe(state));
|
|
* //=> /^(?:(?!\.)(?=.)[^/]*?\.js)$/
|
|
* ```
|
|
* @param {String} `state` The object returned from the `.parse` method.
|
|
* @param {Object} `options`
|
|
* @param {Boolean} `returnOutput` Implementors may use this argument to return the compiled output, instead of a regular expression. This is not exposed on the options to prevent end-users from mutating the result.
|
|
* @param {Boolean} `returnState` Implementors may use this argument to return the state from the parsed glob with the returned regular expression.
|
|
* @return {RegExp} Returns a regex created from the given pattern.
|
|
* @api public
|
|
*/
|
|
|
|
picomatch$1.makeRe = (input, options = {}, returnOutput = false, returnState = false) => {
|
|
if (!input || typeof input !== 'string') {
|
|
throw new TypeError('Expected a non-empty string');
|
|
}
|
|
|
|
let parsed = { negated: false, fastpaths: true };
|
|
|
|
if (options.fastpaths !== false && (input[0] === '.' || input[0] === '*')) {
|
|
parsed.output = parse$1.fastpaths(input, options);
|
|
}
|
|
|
|
if (!parsed.output) {
|
|
parsed = parse$1(input, options);
|
|
}
|
|
|
|
return picomatch$1.compileRe(parsed, options, returnOutput, returnState);
|
|
};
|
|
|
|
/**
|
|
* Create a regular expression from the given regex source string.
|
|
*
|
|
* ```js
|
|
* const picomatch = require('picomatch');
|
|
* // picomatch.toRegex(source[, options]);
|
|
*
|
|
* const { output } = picomatch.parse('*.js');
|
|
* console.log(picomatch.toRegex(output));
|
|
* //=> /^(?:(?!\.)(?=.)[^/]*?\.js)$/
|
|
* ```
|
|
* @param {String} `source` Regular expression source string.
|
|
* @param {Object} `options`
|
|
* @return {RegExp}
|
|
* @api public
|
|
*/
|
|
|
|
picomatch$1.toRegex = (source, options) => {
|
|
try {
|
|
const opts = options || {};
|
|
return new RegExp(source, opts.flags || (opts.nocase ? 'i' : ''));
|
|
} catch (err) {
|
|
if (options && options.debug === true) throw err;
|
|
return /$^/;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Picomatch constants.
|
|
* @return {Object}
|
|
*/
|
|
|
|
picomatch$1.constants = constants;
|
|
|
|
/**
|
|
* Expose "picomatch"
|
|
*/
|
|
|
|
var picomatch_1 = picomatch$1;
|
|
|
|
var picomatch = picomatch_1;
|
|
|
|
var pm = /*@__PURE__*/getDefaultExportFromCjs(picomatch);
|
|
|
|
// Helper since Typescript can't detect readonly arrays with Array.isArray
|
|
function isArray(arg) {
|
|
return Array.isArray(arg);
|
|
}
|
|
function ensureArray(thing) {
|
|
if (isArray(thing))
|
|
return thing;
|
|
if (thing == null)
|
|
return [];
|
|
return [thing];
|
|
}
|
|
|
|
const normalizePath$1 = function normalizePath(filename) {
|
|
return filename.split(require$$0$1.win32.sep).join(require$$0$1.posix.sep);
|
|
};
|
|
|
|
function getMatcherString(id, resolutionBase) {
|
|
if (resolutionBase === false || require$$0$1.isAbsolute(id) || id.startsWith('*')) {
|
|
return normalizePath$1(id);
|
|
}
|
|
// resolve('') is valid and will default to process.cwd()
|
|
const basePath = normalizePath$1(require$$0$1.resolve(resolutionBase || ''))
|
|
// escape all possible (posix + win) path characters that might interfere with regex
|
|
.replace(/[-^$*+?.()|[\]{}]/g, '\\$&');
|
|
// Note that we use posix.join because:
|
|
// 1. the basePath has been normalized to use /
|
|
// 2. the incoming glob (id) matcher, also uses /
|
|
// otherwise Node will force backslash (\) on windows
|
|
return require$$0$1.posix.join(basePath, normalizePath$1(id));
|
|
}
|
|
const createFilter$1 = function createFilter(include, exclude, options) {
|
|
const resolutionBase = options && options.resolve;
|
|
const getMatcher = (id) => id instanceof RegExp
|
|
? id
|
|
: {
|
|
test: (what) => {
|
|
// this refactor is a tad overly verbose but makes for easy debugging
|
|
const pattern = getMatcherString(id, resolutionBase);
|
|
const fn = pm(pattern, { dot: true });
|
|
const result = fn(what);
|
|
return result;
|
|
}
|
|
};
|
|
const includeMatchers = ensureArray(include).map(getMatcher);
|
|
const excludeMatchers = ensureArray(exclude).map(getMatcher);
|
|
return function result(id) {
|
|
if (typeof id !== 'string')
|
|
return false;
|
|
if (/\0/.test(id))
|
|
return false;
|
|
const pathId = normalizePath$1(id);
|
|
for (let i = 0; i < excludeMatchers.length; ++i) {
|
|
const matcher = excludeMatchers[i];
|
|
if (matcher.test(pathId))
|
|
return false;
|
|
}
|
|
for (let i = 0; i < includeMatchers.length; ++i) {
|
|
const matcher = includeMatchers[i];
|
|
if (matcher.test(pathId))
|
|
return true;
|
|
}
|
|
return !includeMatchers.length;
|
|
};
|
|
};
|
|
|
|
const reservedWords = 'break case class catch const continue debugger default delete do else export extends finally for function if import in instanceof let new return super switch this throw try typeof var void while with yield enum await implements package protected static interface private public';
|
|
const builtins = 'arguments Infinity NaN undefined null true false eval uneval isFinite isNaN parseFloat parseInt decodeURI decodeURIComponent encodeURI encodeURIComponent escape unescape Object Function Boolean Symbol Error EvalError InternalError RangeError ReferenceError SyntaxError TypeError URIError Number Math Date String RegExp Array Int8Array Uint8Array Uint8ClampedArray Int16Array Uint16Array Int32Array Uint32Array Float32Array Float64Array Map Set WeakMap WeakSet SIMD ArrayBuffer DataView JSON Promise Generator GeneratorFunction Reflect Proxy Intl';
|
|
const forbiddenIdentifiers = new Set(`${reservedWords} ${builtins}`.split(' '));
|
|
forbiddenIdentifiers.add('');
|
|
|
|
if (process.versions.pnp) {
|
|
try {
|
|
node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (document.currentScript && document.currentScript.src || new URL('node-cjs/publicUtils.cjs', document.baseURI).href)))('pnpapi');
|
|
}
|
|
catch { }
|
|
}
|
|
|
|
const createFilter = createFilter$1;
|
|
const windowsSlashRE = /\\/g;
|
|
function slash(p) {
|
|
return p.replace(windowsSlashRE, '/');
|
|
}
|
|
function isInNodeModules(id) {
|
|
return id.includes('node_modules');
|
|
}
|
|
// TODO: use import()
|
|
const _require = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (document.currentScript && document.currentScript.src || new URL('node-cjs/publicUtils.cjs', document.baseURI).href)));
|
|
// set in bin/vite.js
|
|
const filter = process.env.VITE_DEBUG_FILTER;
|
|
const DEBUG = process.env.DEBUG;
|
|
function createDebugger(namespace, options = {}) {
|
|
const log = debug$1(namespace);
|
|
const { onlyWhenFocused } = options;
|
|
let enabled = log.enabled;
|
|
if (enabled && onlyWhenFocused) {
|
|
const ns = typeof onlyWhenFocused === 'string' ? onlyWhenFocused : namespace;
|
|
enabled = !!DEBUG?.includes(ns);
|
|
}
|
|
if (enabled) {
|
|
return (...args) => {
|
|
if (!filter || args.some((a) => a?.includes?.(filter))) {
|
|
log(...args);
|
|
}
|
|
};
|
|
}
|
|
}
|
|
function testCaseInsensitiveFS() {
|
|
if (!CLIENT_ENTRY.endsWith('client.mjs')) {
|
|
throw new Error(`cannot test case insensitive FS, CLIENT_ENTRY const doesn't contain client.mjs`);
|
|
}
|
|
if (!fs$1.existsSync(CLIENT_ENTRY)) {
|
|
throw new Error('cannot test case insensitive FS, CLIENT_ENTRY does not point to an existing file: ' +
|
|
CLIENT_ENTRY);
|
|
}
|
|
return fs$1.existsSync(CLIENT_ENTRY.replace('client.mjs', 'cLiEnT.mjs'));
|
|
}
|
|
const isCaseInsensitiveFS = testCaseInsensitiveFS();
|
|
const isWindows = os$1.platform() === 'win32';
|
|
const VOLUME_RE = /^[A-Z]:/i;
|
|
function normalizePath(id) {
|
|
return path$3.posix.normalize(isWindows ? slash(id) : id);
|
|
}
|
|
function fsPathFromId(id) {
|
|
const fsPath = normalizePath(id.startsWith(FS_PREFIX) ? id.slice(FS_PREFIX.length) : id);
|
|
return fsPath[0] === '/' || fsPath.match(VOLUME_RE) ? fsPath : `/${fsPath}`;
|
|
}
|
|
function fsPathFromUrl(url) {
|
|
return fsPathFromId(cleanUrl(url));
|
|
}
|
|
/**
|
|
* Check if dir is a parent of file
|
|
*
|
|
* Warning: parameters are not validated, only works with normalized absolute paths
|
|
*
|
|
* @param dir - normalized absolute path
|
|
* @param file - normalized absolute path
|
|
* @returns true if dir is a parent of file
|
|
*/
|
|
function isParentDirectory(dir, file) {
|
|
if (dir[dir.length - 1] !== '/') {
|
|
dir = `${dir}/`;
|
|
}
|
|
return (file.startsWith(dir) ||
|
|
(isCaseInsensitiveFS && file.toLowerCase().startsWith(dir.toLowerCase())));
|
|
}
|
|
/**
|
|
* Check if 2 file name are identical
|
|
*
|
|
* Warning: parameters are not validated, only works with normalized absolute paths
|
|
*
|
|
* @param file1 - normalized absolute path
|
|
* @param file2 - normalized absolute path
|
|
* @returns true if both files url are identical
|
|
*/
|
|
function isSameFileUri(file1, file2) {
|
|
return (file1 === file2 ||
|
|
(isCaseInsensitiveFS && file1.toLowerCase() === file2.toLowerCase()));
|
|
}
|
|
const postfixRE = /[?#].*$/s;
|
|
function cleanUrl(url) {
|
|
return url.replace(postfixRE, '');
|
|
}
|
|
function isObject(value) {
|
|
return Object.prototype.toString.call(value) === '[object Object]';
|
|
}
|
|
function tryStatSync(file) {
|
|
try {
|
|
return fs$1.statSync(file, { throwIfNoEntry: false });
|
|
}
|
|
catch {
|
|
// Ignore errors
|
|
}
|
|
}
|
|
function isFileReadable(filename) {
|
|
try {
|
|
// The "throwIfNoEntry" is a performance optimization for cases where the file does not exist
|
|
if (!fs$1.statSync(filename, { throwIfNoEntry: false })) {
|
|
return false;
|
|
}
|
|
// Check if current process has read permission to the file
|
|
fs$1.accessSync(filename, fs$1.constants.R_OK);
|
|
return true;
|
|
}
|
|
catch {
|
|
return false;
|
|
}
|
|
}
|
|
function arraify(target) {
|
|
return Array.isArray(target) ? target : [target];
|
|
}
|
|
// @ts-expect-error jest only exists when running Jest
|
|
const usingDynamicImport = typeof jest === 'undefined';
|
|
/**
|
|
* Dynamically import files. It will make sure it's not being compiled away by TS/Rollup.
|
|
*
|
|
* As a temporary workaround for Jest's lack of stable ESM support, we fallback to require
|
|
* if we're in a Jest environment.
|
|
* See https://github.com/vitejs/vite/pull/5197#issuecomment-938054077
|
|
*
|
|
* @param file File path to import.
|
|
*/
|
|
usingDynamicImport
|
|
? new Function('file', 'return import(file)')
|
|
: _require;
|
|
path$3.dirname(node_url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (document.currentScript && document.currentScript.src || new URL('node-cjs/publicUtils.cjs', document.baseURI).href))));
|
|
function mergeConfigRecursively(defaults, overrides, rootPath) {
|
|
const merged = { ...defaults };
|
|
for (const key in overrides) {
|
|
const value = overrides[key];
|
|
if (value == null) {
|
|
continue;
|
|
}
|
|
const existing = merged[key];
|
|
if (existing == null) {
|
|
merged[key] = value;
|
|
continue;
|
|
}
|
|
// fields that require special handling
|
|
if (key === 'alias' && (rootPath === 'resolve' || rootPath === '')) {
|
|
merged[key] = mergeAlias(existing, value);
|
|
continue;
|
|
}
|
|
else if (key === 'assetsInclude' && rootPath === '') {
|
|
merged[key] = [].concat(existing, value);
|
|
continue;
|
|
}
|
|
else if (key === 'noExternal' &&
|
|
rootPath === 'ssr' &&
|
|
(existing === true || value === true)) {
|
|
merged[key] = true;
|
|
continue;
|
|
}
|
|
if (Array.isArray(existing) || Array.isArray(value)) {
|
|
merged[key] = [...arraify(existing ?? []), ...arraify(value ?? [])];
|
|
continue;
|
|
}
|
|
if (isObject(existing) && isObject(value)) {
|
|
merged[key] = mergeConfigRecursively(existing, value, rootPath ? `${rootPath}.${key}` : key);
|
|
continue;
|
|
}
|
|
merged[key] = value;
|
|
}
|
|
return merged;
|
|
}
|
|
function mergeConfig(defaults, overrides, isRoot = true) {
|
|
if (typeof defaults === 'function' || typeof overrides === 'function') {
|
|
throw new Error(`Cannot merge config in form of callback`);
|
|
}
|
|
return mergeConfigRecursively(defaults, overrides, isRoot ? '' : '.');
|
|
}
|
|
function mergeAlias(a, b) {
|
|
if (!a)
|
|
return b;
|
|
if (!b)
|
|
return a;
|
|
if (isObject(a) && isObject(b)) {
|
|
return { ...a, ...b };
|
|
}
|
|
// the order is flipped because the alias is resolved from top-down,
|
|
// where the later should have higher priority
|
|
return [...normalizeAlias(b), ...normalizeAlias(a)];
|
|
}
|
|
function normalizeAlias(o = []) {
|
|
return Array.isArray(o)
|
|
? o.map(normalizeSingleAlias)
|
|
: Object.keys(o).map((find) => normalizeSingleAlias({
|
|
find,
|
|
replacement: o[find],
|
|
}));
|
|
}
|
|
// https://github.com/vitejs/vite/issues/1363
|
|
// work around https://github.com/rollup/plugins/issues/759
|
|
function normalizeSingleAlias({ find, replacement, customResolver, }) {
|
|
if (typeof find === 'string' &&
|
|
find[find.length - 1] === '/' &&
|
|
replacement[replacement.length - 1] === '/') {
|
|
find = find.slice(0, find.length - 1);
|
|
replacement = replacement.slice(0, replacement.length - 1);
|
|
}
|
|
const alias = {
|
|
find,
|
|
replacement,
|
|
};
|
|
if (customResolver) {
|
|
alias.customResolver = customResolver;
|
|
}
|
|
return alias;
|
|
}
|
|
|
|
// This file will be built for both ESM and CJS. Avoid relying on other modules as possible.
|
|
// copy from constants.ts
|
|
const CSS_LANGS_RE =
|
|
// eslint-disable-next-line regexp/no-unused-capturing-group
|
|
/\.(css|less|sass|scss|styl|stylus|pcss|postcss|sss)(?:$|\?)/;
|
|
const isCSSRequest = (request) => CSS_LANGS_RE.test(request);
|
|
// Use splitVendorChunkPlugin() to get the same manualChunks strategy as Vite 2.7
|
|
// We don't recommend using this strategy as a general solution moving forward
|
|
// splitVendorChunk is a simple index/vendor strategy that was used in Vite
|
|
// until v2.8. It is exposed to let people continue to use it in case it was
|
|
// working well for their setups.
|
|
// The cache needs to be reset on buildStart for watch mode to work correctly
|
|
// Don't use this manualChunks strategy for ssr, lib mode, and 'umd' or 'iife'
|
|
class SplitVendorChunkCache {
|
|
constructor() {
|
|
this.cache = new Map();
|
|
}
|
|
reset() {
|
|
this.cache = new Map();
|
|
}
|
|
}
|
|
function splitVendorChunk(options = {}) {
|
|
const cache = options.cache ?? new SplitVendorChunkCache();
|
|
return (id, { getModuleInfo }) => {
|
|
if (isInNodeModules(id) &&
|
|
!isCSSRequest(id) &&
|
|
staticImportedByEntry(id, getModuleInfo, cache.cache)) {
|
|
return 'vendor';
|
|
}
|
|
};
|
|
}
|
|
function staticImportedByEntry(id, getModuleInfo, cache, importStack = []) {
|
|
if (cache.has(id)) {
|
|
return cache.get(id);
|
|
}
|
|
if (importStack.includes(id)) {
|
|
// circular deps!
|
|
cache.set(id, false);
|
|
return false;
|
|
}
|
|
const mod = getModuleInfo(id);
|
|
if (!mod) {
|
|
cache.set(id, false);
|
|
return false;
|
|
}
|
|
if (mod.isEntry) {
|
|
cache.set(id, true);
|
|
return true;
|
|
}
|
|
const someImporterIs = mod.importers.some((importer) => staticImportedByEntry(importer, getModuleInfo, cache, importStack.concat(id)));
|
|
cache.set(id, someImporterIs);
|
|
return someImporterIs;
|
|
}
|
|
function splitVendorChunkPlugin() {
|
|
const caches = [];
|
|
function createSplitVendorChunk(output, config) {
|
|
const cache = new SplitVendorChunkCache();
|
|
caches.push(cache);
|
|
const build = config.build ?? {};
|
|
const format = output?.format;
|
|
if (!build.ssr && !build.lib && format !== 'umd' && format !== 'iife') {
|
|
return splitVendorChunk({ cache });
|
|
}
|
|
}
|
|
return {
|
|
name: 'vite:split-vendor-chunk',
|
|
config(config) {
|
|
let outputs = config?.build?.rollupOptions?.output;
|
|
if (outputs) {
|
|
outputs = Array.isArray(outputs) ? outputs : [outputs];
|
|
for (const output of outputs) {
|
|
const viteManualChunks = createSplitVendorChunk(output, config);
|
|
if (viteManualChunks) {
|
|
if (output.manualChunks) {
|
|
if (typeof output.manualChunks === 'function') {
|
|
const userManualChunks = output.manualChunks;
|
|
output.manualChunks = (id, api) => {
|
|
return userManualChunks(id, api) ?? viteManualChunks(id, api);
|
|
};
|
|
}
|
|
else {
|
|
// else, leave the object form of manualChunks untouched, as
|
|
// we can't safely replicate rollup handling.
|
|
// eslint-disable-next-line no-console
|
|
console.warn("(!) the `splitVendorChunk` plugin doesn't have any effect when using the object form of `build.rollupOptions.output.manualChunks`. Consider using the function form instead.");
|
|
}
|
|
}
|
|
else {
|
|
output.manualChunks = viteManualChunks;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
return {
|
|
build: {
|
|
rollupOptions: {
|
|
output: {
|
|
manualChunks: createSplitVendorChunk({}, config),
|
|
},
|
|
},
|
|
},
|
|
};
|
|
}
|
|
},
|
|
buildStart() {
|
|
caches.forEach((cache) => cache.reset());
|
|
},
|
|
};
|
|
}
|
|
|
|
/*!
|
|
* etag
|
|
* Copyright(c) 2014-2016 Douglas Christopher Wilson
|
|
* MIT Licensed
|
|
*/
|
|
|
|
/**
|
|
* Module exports.
|
|
* @public
|
|
*/
|
|
|
|
var etag_1 = etag;
|
|
|
|
/**
|
|
* Module dependencies.
|
|
* @private
|
|
*/
|
|
|
|
var crypto$1 = require$$0$2;
|
|
var Stats = fs$2.Stats;
|
|
|
|
/**
|
|
* Module variables.
|
|
* @private
|
|
*/
|
|
|
|
var toString = Object.prototype.toString;
|
|
|
|
/**
|
|
* Generate an entity tag.
|
|
*
|
|
* @param {Buffer|string} entity
|
|
* @return {string}
|
|
* @private
|
|
*/
|
|
|
|
function entitytag (entity) {
|
|
if (entity.length === 0) {
|
|
// fast-path empty
|
|
return '"0-2jmj7l5rSw0yVb/vlWAYkK/YBwk"'
|
|
}
|
|
|
|
// compute hash of entity
|
|
var hash = crypto$1
|
|
.createHash('sha1')
|
|
.update(entity, 'utf8')
|
|
.digest('base64')
|
|
.substring(0, 27);
|
|
|
|
// compute length of entity
|
|
var len = typeof entity === 'string'
|
|
? Buffer.byteLength(entity, 'utf8')
|
|
: entity.length;
|
|
|
|
return '"' + len.toString(16) + '-' + hash + '"'
|
|
}
|
|
|
|
/**
|
|
* Create a simple ETag.
|
|
*
|
|
* @param {string|Buffer|Stats} entity
|
|
* @param {object} [options]
|
|
* @param {boolean} [options.weak]
|
|
* @return {String}
|
|
* @public
|
|
*/
|
|
|
|
function etag (entity, options) {
|
|
if (entity == null) {
|
|
throw new TypeError('argument entity is required')
|
|
}
|
|
|
|
// support fs.Stats object
|
|
var isStats = isstats(entity);
|
|
var weak = options && typeof options.weak === 'boolean'
|
|
? options.weak
|
|
: isStats;
|
|
|
|
// validate argument
|
|
if (!isStats && typeof entity !== 'string' && !Buffer.isBuffer(entity)) {
|
|
throw new TypeError('argument entity must be string, Buffer, or fs.Stats')
|
|
}
|
|
|
|
// generate entity tag
|
|
var tag = isStats
|
|
? stattag(entity)
|
|
: entitytag(entity);
|
|
|
|
return weak
|
|
? 'W/' + tag
|
|
: tag
|
|
}
|
|
|
|
/**
|
|
* Determine if object is a Stats object.
|
|
*
|
|
* @param {object} obj
|
|
* @return {boolean}
|
|
* @api private
|
|
*/
|
|
|
|
function isstats (obj) {
|
|
// genuine fs.Stats
|
|
if (typeof Stats === 'function' && obj instanceof Stats) {
|
|
return true
|
|
}
|
|
|
|
// quack quack
|
|
return obj && typeof obj === 'object' &&
|
|
'ctime' in obj && toString.call(obj.ctime) === '[object Date]' &&
|
|
'mtime' in obj && toString.call(obj.mtime) === '[object Date]' &&
|
|
'ino' in obj && typeof obj.ino === 'number' &&
|
|
'size' in obj && typeof obj.size === 'number'
|
|
}
|
|
|
|
/**
|
|
* Generate a tag for a stat.
|
|
*
|
|
* @param {object} stat
|
|
* @return {string}
|
|
* @private
|
|
*/
|
|
|
|
function stattag (stat) {
|
|
var mtime = stat.mtime.getTime().toString(16);
|
|
var size = stat.size.toString(16);
|
|
|
|
return '"' + size + '-' + mtime + '"'
|
|
}
|
|
|
|
var getEtag = /*@__PURE__*/getDefaultExportFromCjs(etag_1);
|
|
|
|
const debug = createDebugger('vite:sourcemap', {
|
|
onlyWhenFocused: true,
|
|
});
|
|
function genSourceMapUrl(map) {
|
|
if (typeof map !== 'string') {
|
|
map = JSON.stringify(map);
|
|
}
|
|
return `data:application/json;base64,${Buffer.from(map).toString('base64')}`;
|
|
}
|
|
function getCodeWithSourcemap(type, code, map) {
|
|
if (debug) {
|
|
code += `\n/*${JSON.stringify(map, null, 2).replace(/\*\//g, '*\\/')}*/\n`;
|
|
}
|
|
if (type === 'js') {
|
|
code += `\n//# sourceMappingURL=${genSourceMapUrl(map)}`;
|
|
}
|
|
else if (type === 'css') {
|
|
code += `\n/*# sourceMappingURL=${genSourceMapUrl(map)} */`;
|
|
}
|
|
return code;
|
|
}
|
|
|
|
const alias = {
|
|
js: 'application/javascript',
|
|
css: 'text/css',
|
|
html: 'text/html',
|
|
json: 'application/json',
|
|
};
|
|
function send(req, res, content, type, options) {
|
|
const { etag = getEtag(content, { weak: true }), cacheControl = 'no-cache', headers, map, } = options;
|
|
if (res.writableEnded) {
|
|
return;
|
|
}
|
|
if (req.headers['if-none-match'] === etag) {
|
|
res.statusCode = 304;
|
|
res.end();
|
|
return;
|
|
}
|
|
res.setHeader('Content-Type', alias[type] || type);
|
|
res.setHeader('Cache-Control', cacheControl);
|
|
res.setHeader('Etag', etag);
|
|
if (headers) {
|
|
for (const name in headers) {
|
|
res.setHeader(name, headers[name]);
|
|
}
|
|
}
|
|
// inject source map reference
|
|
if (map && map.mappings) {
|
|
if (type === 'js' || type === 'css') {
|
|
content = getCodeWithSourcemap(type, content.toString(), map);
|
|
}
|
|
}
|
|
res.statusCode = 200;
|
|
res.end(content);
|
|
return;
|
|
}
|
|
|
|
/* eslint no-console: 0 */
|
|
const LogLevels = {
|
|
silent: 0,
|
|
error: 1,
|
|
warn: 2,
|
|
info: 3,
|
|
};
|
|
let lastType;
|
|
let lastMsg;
|
|
let sameCount = 0;
|
|
function clearScreen() {
|
|
const repeatCount = process.stdout.rows - 2;
|
|
const blank = repeatCount > 0 ? '\n'.repeat(repeatCount) : '';
|
|
console.log(blank);
|
|
readline.cursorTo(process.stdout, 0, 0);
|
|
readline.clearScreenDown(process.stdout);
|
|
}
|
|
function createLogger(level = 'info', options = {}) {
|
|
if (options.customLogger) {
|
|
return options.customLogger;
|
|
}
|
|
const timeFormatter = new Intl.DateTimeFormat(undefined, {
|
|
hour: 'numeric',
|
|
minute: 'numeric',
|
|
second: 'numeric',
|
|
});
|
|
const loggedErrors = new WeakSet();
|
|
const { prefix = '[vite]', allowClearScreen = true } = options;
|
|
const thresh = LogLevels[level];
|
|
const canClearScreen = allowClearScreen && process.stdout.isTTY && !process.env.CI;
|
|
const clear = canClearScreen ? clearScreen : () => { };
|
|
function output(type, msg, options = {}) {
|
|
if (thresh >= LogLevels[type]) {
|
|
const method = type === 'info' ? 'log' : type;
|
|
const format = () => {
|
|
if (options.timestamp) {
|
|
const tag = type === 'info'
|
|
? colors.cyan(colors.bold(prefix))
|
|
: type === 'warn'
|
|
? colors.yellow(colors.bold(prefix))
|
|
: colors.red(colors.bold(prefix));
|
|
return `${colors.dim(timeFormatter.format(new Date()))} ${tag} ${msg}`;
|
|
}
|
|
else {
|
|
return msg;
|
|
}
|
|
};
|
|
if (options.error) {
|
|
loggedErrors.add(options.error);
|
|
}
|
|
if (canClearScreen) {
|
|
if (type === lastType && msg === lastMsg) {
|
|
sameCount++;
|
|
clear();
|
|
console[method](format(), colors.yellow(`(x${sameCount + 1})`));
|
|
}
|
|
else {
|
|
sameCount = 0;
|
|
lastMsg = msg;
|
|
lastType = type;
|
|
if (options.clear) {
|
|
clear();
|
|
}
|
|
console[method](format());
|
|
}
|
|
}
|
|
else {
|
|
console[method](format());
|
|
}
|
|
}
|
|
}
|
|
const warnedMessages = new Set();
|
|
const logger = {
|
|
hasWarned: false,
|
|
info(msg, opts) {
|
|
output('info', msg, opts);
|
|
},
|
|
warn(msg, opts) {
|
|
logger.hasWarned = true;
|
|
output('warn', msg, opts);
|
|
},
|
|
warnOnce(msg, opts) {
|
|
if (warnedMessages.has(msg))
|
|
return;
|
|
logger.hasWarned = true;
|
|
output('warn', msg, opts);
|
|
warnedMessages.add(msg);
|
|
},
|
|
error(msg, opts) {
|
|
logger.hasWarned = true;
|
|
output('error', msg, opts);
|
|
},
|
|
clearScreen(type) {
|
|
if (thresh >= LogLevels[type]) {
|
|
clear();
|
|
}
|
|
},
|
|
hasErrorLogged(error) {
|
|
return loggedErrors.has(error);
|
|
},
|
|
};
|
|
return logger;
|
|
}
|
|
|
|
// https://github.com/vitejs/vite/issues/2820#issuecomment-812495079
|
|
const ROOT_FILES = [
|
|
// '.git',
|
|
// https://pnpm.io/workspaces/
|
|
'pnpm-workspace.yaml',
|
|
// https://rushjs.io/pages/advanced/config_files/
|
|
// 'rush.json',
|
|
// https://nx.dev/latest/react/getting-started/nx-setup
|
|
// 'workspace.json',
|
|
// 'nx.json',
|
|
// https://github.com/lerna/lerna#lernajson
|
|
'lerna.json',
|
|
];
|
|
// npm: https://docs.npmjs.com/cli/v7/using-npm/workspaces#installing-workspaces
|
|
// yarn: https://classic.yarnpkg.com/en/docs/workspaces/#toc-how-to-use-it
|
|
function hasWorkspacePackageJSON(root) {
|
|
const path = path$3.join(root, 'package.json');
|
|
if (!isFileReadable(path)) {
|
|
return false;
|
|
}
|
|
const content = JSON.parse(fs$1.readFileSync(path, 'utf-8')) || {};
|
|
return !!content.workspaces;
|
|
}
|
|
function hasRootFile(root) {
|
|
return ROOT_FILES.some((file) => fs$1.existsSync(path$3.join(root, file)));
|
|
}
|
|
function hasPackageJSON(root) {
|
|
const path = path$3.join(root, 'package.json');
|
|
return fs$1.existsSync(path);
|
|
}
|
|
/**
|
|
* Search up for the nearest `package.json`
|
|
*/
|
|
function searchForPackageRoot(current, root = current) {
|
|
if (hasPackageJSON(current))
|
|
return current;
|
|
const dir = path$3.dirname(current);
|
|
// reach the fs root
|
|
if (!dir || dir === current)
|
|
return root;
|
|
return searchForPackageRoot(dir, root);
|
|
}
|
|
/**
|
|
* Search up for the nearest workspace root
|
|
*/
|
|
function searchForWorkspaceRoot(current, root = searchForPackageRoot(current)) {
|
|
if (hasRootFile(current))
|
|
return current;
|
|
if (hasWorkspacePackageJSON(current))
|
|
return current;
|
|
const dir = path$3.dirname(current);
|
|
// reach the fs root
|
|
if (!dir || dir === current)
|
|
return root;
|
|
return searchForWorkspaceRoot(dir, root);
|
|
}
|
|
|
|
/**
|
|
* Check if the url is allowed to be served, via the `server.fs` config.
|
|
*/
|
|
function isFileServingAllowed(url, server) {
|
|
if (!server.config.server.fs.strict)
|
|
return true;
|
|
const file = fsPathFromUrl(url);
|
|
if (server._fsDenyGlob(file))
|
|
return false;
|
|
if (server.moduleGraph.safeModulesPath.has(file))
|
|
return true;
|
|
if (server.config.server.fs.allow.some((uri) => isSameFileUri(uri, file) || isParentDirectory(uri, file)))
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
var main$1 = {exports: {}};
|
|
|
|
var name = "dotenv";
|
|
var version$1 = "16.3.1";
|
|
var description = "Loads environment variables from .env file";
|
|
var main = "lib/main.js";
|
|
var types = "lib/main.d.ts";
|
|
var exports$1 = {
|
|
".": {
|
|
types: "./lib/main.d.ts",
|
|
require: "./lib/main.js",
|
|
"default": "./lib/main.js"
|
|
},
|
|
"./config": "./config.js",
|
|
"./config.js": "./config.js",
|
|
"./lib/env-options": "./lib/env-options.js",
|
|
"./lib/env-options.js": "./lib/env-options.js",
|
|
"./lib/cli-options": "./lib/cli-options.js",
|
|
"./lib/cli-options.js": "./lib/cli-options.js",
|
|
"./package.json": "./package.json"
|
|
};
|
|
var scripts = {
|
|
"dts-check": "tsc --project tests/types/tsconfig.json",
|
|
lint: "standard",
|
|
"lint-readme": "standard-markdown",
|
|
pretest: "npm run lint && npm run dts-check",
|
|
test: "tap tests/*.js --100 -Rspec",
|
|
prerelease: "npm test",
|
|
release: "standard-version"
|
|
};
|
|
var repository = {
|
|
type: "git",
|
|
url: "git://github.com/motdotla/dotenv.git"
|
|
};
|
|
var funding = "https://github.com/motdotla/dotenv?sponsor=1";
|
|
var keywords = [
|
|
"dotenv",
|
|
"env",
|
|
".env",
|
|
"environment",
|
|
"variables",
|
|
"config",
|
|
"settings"
|
|
];
|
|
var readmeFilename = "README.md";
|
|
var license = "BSD-2-Clause";
|
|
var devDependencies = {
|
|
"@definitelytyped/dtslint": "^0.0.133",
|
|
"@types/node": "^18.11.3",
|
|
decache: "^4.6.1",
|
|
sinon: "^14.0.1",
|
|
standard: "^17.0.0",
|
|
"standard-markdown": "^7.1.0",
|
|
"standard-version": "^9.5.0",
|
|
tap: "^16.3.0",
|
|
tar: "^6.1.11",
|
|
typescript: "^4.8.4"
|
|
};
|
|
var engines = {
|
|
node: ">=12"
|
|
};
|
|
var browser = {
|
|
fs: false
|
|
};
|
|
var require$$4 = {
|
|
name: name,
|
|
version: version$1,
|
|
description: description,
|
|
main: main,
|
|
types: types,
|
|
exports: exports$1,
|
|
scripts: scripts,
|
|
repository: repository,
|
|
funding: funding,
|
|
keywords: keywords,
|
|
readmeFilename: readmeFilename,
|
|
license: license,
|
|
devDependencies: devDependencies,
|
|
engines: engines,
|
|
browser: browser
|
|
};
|
|
|
|
const fs = fs$2;
|
|
const path = require$$0$1;
|
|
const os = require$$2;
|
|
const crypto = require$$0$2;
|
|
const packageJson = require$$4;
|
|
|
|
const version = packageJson.version;
|
|
|
|
const LINE = /(?:^|^)\s*(?:export\s+)?([\w.-]+)(?:\s*=\s*?|:\s+?)(\s*'(?:\\'|[^'])*'|\s*"(?:\\"|[^"])*"|\s*`(?:\\`|[^`])*`|[^#\r\n]+)?\s*(?:#.*)?(?:$|$)/mg;
|
|
|
|
// Parse src into an Object
|
|
function parse (src) {
|
|
const obj = {};
|
|
|
|
// Convert buffer to string
|
|
let lines = src.toString();
|
|
|
|
// Convert line breaks to same format
|
|
lines = lines.replace(/\r\n?/mg, '\n');
|
|
|
|
let match;
|
|
while ((match = LINE.exec(lines)) != null) {
|
|
const key = match[1];
|
|
|
|
// Default undefined or null to empty string
|
|
let value = (match[2] || '');
|
|
|
|
// Remove whitespace
|
|
value = value.trim();
|
|
|
|
// Check if double quoted
|
|
const maybeQuote = value[0];
|
|
|
|
// Remove surrounding quotes
|
|
value = value.replace(/^(['"`])([\s\S]*)\1$/mg, '$2');
|
|
|
|
// Expand newlines if double quoted
|
|
if (maybeQuote === '"') {
|
|
value = value.replace(/\\n/g, '\n');
|
|
value = value.replace(/\\r/g, '\r');
|
|
}
|
|
|
|
// Add to object
|
|
obj[key] = value;
|
|
}
|
|
|
|
return obj
|
|
}
|
|
|
|
function _parseVault (options) {
|
|
const vaultPath = _vaultPath(options);
|
|
|
|
// Parse .env.vault
|
|
const result = DotenvModule.configDotenv({ path: vaultPath });
|
|
if (!result.parsed) {
|
|
throw new Error(`MISSING_DATA: Cannot parse ${vaultPath} for an unknown reason`)
|
|
}
|
|
|
|
// handle scenario for comma separated keys - for use with key rotation
|
|
// example: DOTENV_KEY="dotenv://:key_1234@dotenv.org/vault/.env.vault?environment=prod,dotenv://:key_7890@dotenv.org/vault/.env.vault?environment=prod"
|
|
const keys = _dotenvKey(options).split(',');
|
|
const length = keys.length;
|
|
|
|
let decrypted;
|
|
for (let i = 0; i < length; i++) {
|
|
try {
|
|
// Get full key
|
|
const key = keys[i].trim();
|
|
|
|
// Get instructions for decrypt
|
|
const attrs = _instructions(result, key);
|
|
|
|
// Decrypt
|
|
decrypted = DotenvModule.decrypt(attrs.ciphertext, attrs.key);
|
|
|
|
break
|
|
} catch (error) {
|
|
// last key
|
|
if (i + 1 >= length) {
|
|
throw error
|
|
}
|
|
// try next key
|
|
}
|
|
}
|
|
|
|
// Parse decrypted .env string
|
|
return DotenvModule.parse(decrypted)
|
|
}
|
|
|
|
function _log (message) {
|
|
console.log(`[dotenv@${version}][INFO] ${message}`);
|
|
}
|
|
|
|
function _warn (message) {
|
|
console.log(`[dotenv@${version}][WARN] ${message}`);
|
|
}
|
|
|
|
function _debug (message) {
|
|
console.log(`[dotenv@${version}][DEBUG] ${message}`);
|
|
}
|
|
|
|
function _dotenvKey (options) {
|
|
// prioritize developer directly setting options.DOTENV_KEY
|
|
if (options && options.DOTENV_KEY && options.DOTENV_KEY.length > 0) {
|
|
return options.DOTENV_KEY
|
|
}
|
|
|
|
// secondary infra already contains a DOTENV_KEY environment variable
|
|
if (process.env.DOTENV_KEY && process.env.DOTENV_KEY.length > 0) {
|
|
return process.env.DOTENV_KEY
|
|
}
|
|
|
|
// fallback to empty string
|
|
return ''
|
|
}
|
|
|
|
function _instructions (result, dotenvKey) {
|
|
// Parse DOTENV_KEY. Format is a URI
|
|
let uri;
|
|
try {
|
|
uri = new URL(dotenvKey);
|
|
} catch (error) {
|
|
if (error.code === 'ERR_INVALID_URL') {
|
|
throw new Error('INVALID_DOTENV_KEY: Wrong format. Must be in valid uri format like dotenv://:key_1234@dotenv.org/vault/.env.vault?environment=development')
|
|
}
|
|
|
|
throw error
|
|
}
|
|
|
|
// Get decrypt key
|
|
const key = uri.password;
|
|
if (!key) {
|
|
throw new Error('INVALID_DOTENV_KEY: Missing key part')
|
|
}
|
|
|
|
// Get environment
|
|
const environment = uri.searchParams.get('environment');
|
|
if (!environment) {
|
|
throw new Error('INVALID_DOTENV_KEY: Missing environment part')
|
|
}
|
|
|
|
// Get ciphertext payload
|
|
const environmentKey = `DOTENV_VAULT_${environment.toUpperCase()}`;
|
|
const ciphertext = result.parsed[environmentKey]; // DOTENV_VAULT_PRODUCTION
|
|
if (!ciphertext) {
|
|
throw new Error(`NOT_FOUND_DOTENV_ENVIRONMENT: Cannot locate environment ${environmentKey} in your .env.vault file.`)
|
|
}
|
|
|
|
return { ciphertext, key }
|
|
}
|
|
|
|
function _vaultPath (options) {
|
|
let dotenvPath = path.resolve(process.cwd(), '.env');
|
|
|
|
if (options && options.path && options.path.length > 0) {
|
|
dotenvPath = options.path;
|
|
}
|
|
|
|
// Locate .env.vault
|
|
return dotenvPath.endsWith('.vault') ? dotenvPath : `${dotenvPath}.vault`
|
|
}
|
|
|
|
function _resolveHome (envPath) {
|
|
return envPath[0] === '~' ? path.join(os.homedir(), envPath.slice(1)) : envPath
|
|
}
|
|
|
|
function _configVault (options) {
|
|
_log('Loading env from encrypted .env.vault');
|
|
|
|
const parsed = DotenvModule._parseVault(options);
|
|
|
|
let processEnv = process.env;
|
|
if (options && options.processEnv != null) {
|
|
processEnv = options.processEnv;
|
|
}
|
|
|
|
DotenvModule.populate(processEnv, parsed, options);
|
|
|
|
return { parsed }
|
|
}
|
|
|
|
function configDotenv (options) {
|
|
let dotenvPath = path.resolve(process.cwd(), '.env');
|
|
let encoding = 'utf8';
|
|
const debug = Boolean(options && options.debug);
|
|
|
|
if (options) {
|
|
if (options.path != null) {
|
|
dotenvPath = _resolveHome(options.path);
|
|
}
|
|
if (options.encoding != null) {
|
|
encoding = options.encoding;
|
|
}
|
|
}
|
|
|
|
try {
|
|
// Specifying an encoding returns a string instead of a buffer
|
|
const parsed = DotenvModule.parse(fs.readFileSync(dotenvPath, { encoding }));
|
|
|
|
let processEnv = process.env;
|
|
if (options && options.processEnv != null) {
|
|
processEnv = options.processEnv;
|
|
}
|
|
|
|
DotenvModule.populate(processEnv, parsed, options);
|
|
|
|
return { parsed }
|
|
} catch (e) {
|
|
if (debug) {
|
|
_debug(`Failed to load ${dotenvPath} ${e.message}`);
|
|
}
|
|
|
|
return { error: e }
|
|
}
|
|
}
|
|
|
|
// Populates process.env from .env file
|
|
function config (options) {
|
|
const vaultPath = _vaultPath(options);
|
|
|
|
// fallback to original dotenv if DOTENV_KEY is not set
|
|
if (_dotenvKey(options).length === 0) {
|
|
return DotenvModule.configDotenv(options)
|
|
}
|
|
|
|
// dotenvKey exists but .env.vault file does not exist
|
|
if (!fs.existsSync(vaultPath)) {
|
|
_warn(`You set DOTENV_KEY but you are missing a .env.vault file at ${vaultPath}. Did you forget to build it?`);
|
|
|
|
return DotenvModule.configDotenv(options)
|
|
}
|
|
|
|
return DotenvModule._configVault(options)
|
|
}
|
|
|
|
function decrypt (encrypted, keyStr) {
|
|
const key = Buffer.from(keyStr.slice(-64), 'hex');
|
|
let ciphertext = Buffer.from(encrypted, 'base64');
|
|
|
|
const nonce = ciphertext.slice(0, 12);
|
|
const authTag = ciphertext.slice(-16);
|
|
ciphertext = ciphertext.slice(12, -16);
|
|
|
|
try {
|
|
const aesgcm = crypto.createDecipheriv('aes-256-gcm', key, nonce);
|
|
aesgcm.setAuthTag(authTag);
|
|
return `${aesgcm.update(ciphertext)}${aesgcm.final()}`
|
|
} catch (error) {
|
|
const isRange = error instanceof RangeError;
|
|
const invalidKeyLength = error.message === 'Invalid key length';
|
|
const decryptionFailed = error.message === 'Unsupported state or unable to authenticate data';
|
|
|
|
if (isRange || invalidKeyLength) {
|
|
const msg = 'INVALID_DOTENV_KEY: It must be 64 characters long (or more)';
|
|
throw new Error(msg)
|
|
} else if (decryptionFailed) {
|
|
const msg = 'DECRYPTION_FAILED: Please check your DOTENV_KEY';
|
|
throw new Error(msg)
|
|
} else {
|
|
console.error('Error: ', error.code);
|
|
console.error('Error: ', error.message);
|
|
throw error
|
|
}
|
|
}
|
|
}
|
|
|
|
// Populate process.env with parsed values
|
|
function populate (processEnv, parsed, options = {}) {
|
|
const debug = Boolean(options && options.debug);
|
|
const override = Boolean(options && options.override);
|
|
|
|
if (typeof parsed !== 'object') {
|
|
throw new Error('OBJECT_REQUIRED: Please check the processEnv argument being passed to populate')
|
|
}
|
|
|
|
// Set process.env
|
|
for (const key of Object.keys(parsed)) {
|
|
if (Object.prototype.hasOwnProperty.call(processEnv, key)) {
|
|
if (override === true) {
|
|
processEnv[key] = parsed[key];
|
|
}
|
|
|
|
if (debug) {
|
|
if (override === true) {
|
|
_debug(`"${key}" is already defined and WAS overwritten`);
|
|
} else {
|
|
_debug(`"${key}" is already defined and was NOT overwritten`);
|
|
}
|
|
}
|
|
} else {
|
|
processEnv[key] = parsed[key];
|
|
}
|
|
}
|
|
}
|
|
|
|
const DotenvModule = {
|
|
configDotenv,
|
|
_configVault,
|
|
_parseVault,
|
|
config,
|
|
decrypt,
|
|
parse,
|
|
populate
|
|
};
|
|
|
|
main$1.exports.configDotenv = DotenvModule.configDotenv;
|
|
main$1.exports._configVault = DotenvModule._configVault;
|
|
main$1.exports._parseVault = DotenvModule._parseVault;
|
|
main$1.exports.config = DotenvModule.config;
|
|
main$1.exports.decrypt = DotenvModule.decrypt;
|
|
var parse_1 = main$1.exports.parse = DotenvModule.parse;
|
|
main$1.exports.populate = DotenvModule.populate;
|
|
|
|
main$1.exports = DotenvModule;
|
|
|
|
function _interpolate (envValue, environment, config) {
|
|
const matches = envValue.match(/(.?\${*[\w]*(?::-[\w/]*)?}*)/g) || [];
|
|
|
|
return matches.reduce(function (newEnv, match, index) {
|
|
const parts = /(.?)\${*([\w]*(?::-[\w/]*)?)?}*/g.exec(match);
|
|
if (!parts || parts.length === 0) {
|
|
return newEnv
|
|
}
|
|
|
|
const prefix = parts[1];
|
|
|
|
let value, replacePart;
|
|
|
|
if (prefix === '\\') {
|
|
replacePart = parts[0];
|
|
value = replacePart.replace('\\$', '$');
|
|
} else {
|
|
// PATCH: compatible with env variables ended with unescaped $
|
|
if(!parts[2]) {
|
|
return newEnv
|
|
}
|
|
const keyParts = parts[2].split(':-');
|
|
const key = keyParts[0];
|
|
replacePart = parts[0].substring(prefix.length);
|
|
// process.env value 'wins' over .env file's value
|
|
value = Object.prototype.hasOwnProperty.call(environment, key)
|
|
? environment[key]
|
|
: (config.parsed[key] || keyParts[1] || '');
|
|
|
|
// If the value is found, remove nested expansions.
|
|
if (keyParts.length > 1 && value) {
|
|
const replaceNested = matches[index + 1];
|
|
matches[index + 1] = '';
|
|
|
|
newEnv = newEnv.replace(replaceNested, '');
|
|
}
|
|
// Resolve recursive interpolations
|
|
value = _interpolate(value, environment, config);
|
|
}
|
|
|
|
return newEnv.replace(replacePart, value)
|
|
}, envValue)
|
|
}
|
|
|
|
function expand (config) {
|
|
// if ignoring process.env, use a blank object
|
|
const environment = config.ignoreProcessEnv ? {} : process.env;
|
|
|
|
for (const configKey in config.parsed) {
|
|
const value = Object.prototype.hasOwnProperty.call(environment, configKey) ? environment[configKey] : config.parsed[configKey];
|
|
|
|
config.parsed[configKey] = _interpolate(value, environment, config);
|
|
}
|
|
|
|
// PATCH: don't write to process.env
|
|
// for (const processKey in config.parsed) {
|
|
// environment[processKey] = config.parsed[processKey]
|
|
// }
|
|
|
|
return config
|
|
}
|
|
|
|
var expand_1 = expand;
|
|
|
|
function loadEnv(mode, envDir, prefixes = 'VITE_') {
|
|
if (mode === 'local') {
|
|
throw new Error(`"local" cannot be used as a mode name because it conflicts with ` +
|
|
`the .local postfix for .env files.`);
|
|
}
|
|
prefixes = arraify(prefixes);
|
|
const env = {};
|
|
const envFiles = [
|
|
/** default file */ `.env`,
|
|
/** local file */ `.env.local`,
|
|
/** mode file */ `.env.${mode}`,
|
|
/** mode local file */ `.env.${mode}.local`,
|
|
];
|
|
const parsed = Object.fromEntries(envFiles.flatMap((file) => {
|
|
const filePath = path$3.join(envDir, file);
|
|
if (!tryStatSync(filePath)?.isFile())
|
|
return [];
|
|
return Object.entries(parse_1(fs$1.readFileSync(filePath)));
|
|
}));
|
|
// test NODE_ENV override before expand as otherwise process.env.NODE_ENV would override this
|
|
if (parsed.NODE_ENV && process.env.VITE_USER_NODE_ENV === undefined) {
|
|
process.env.VITE_USER_NODE_ENV = parsed.NODE_ENV;
|
|
}
|
|
// support BROWSER and BROWSER_ARGS env variables
|
|
if (parsed.BROWSER && process.env.BROWSER === undefined) {
|
|
process.env.BROWSER = parsed.BROWSER;
|
|
}
|
|
if (parsed.BROWSER_ARGS && process.env.BROWSER_ARGS === undefined) {
|
|
process.env.BROWSER_ARGS = parsed.BROWSER_ARGS;
|
|
}
|
|
// let environment variables use each other
|
|
// `expand` patched in patches/dotenv-expand@9.0.0.patch
|
|
expand_1({ parsed });
|
|
// only keys that start with prefix are exposed to client
|
|
for (const [key, value] of Object.entries(parsed)) {
|
|
if (prefixes.some((prefix) => key.startsWith(prefix))) {
|
|
env[key] = value;
|
|
}
|
|
}
|
|
// check if there are actual env variables starting with VITE_*
|
|
// these are typically provided inline and should be prioritized
|
|
for (const key in process.env) {
|
|
if (prefixes.some((prefix) => key.startsWith(prefix))) {
|
|
env[key] = process.env[key];
|
|
}
|
|
}
|
|
return env;
|
|
}
|
|
function resolveEnvPrefix({ envPrefix = 'VITE_', }) {
|
|
envPrefix = arraify(envPrefix);
|
|
if (envPrefix.some((prefix) => prefix === '')) {
|
|
throw new Error(`envPrefix option contains value '', which could lead unexpected exposure of sensitive information.`);
|
|
}
|
|
return envPrefix;
|
|
}
|
|
|
|
exports.esbuildVersion = esbuild.version;
|
|
exports.rollupVersion = rollup.VERSION;
|
|
exports.createFilter = createFilter;
|
|
exports.createLogger = createLogger;
|
|
exports.isCSSRequest = isCSSRequest;
|
|
exports.isFileServingAllowed = isFileServingAllowed;
|
|
exports.loadEnv = loadEnv;
|
|
exports.mergeAlias = mergeAlias;
|
|
exports.mergeConfig = mergeConfig;
|
|
exports.normalizePath = normalizePath;
|
|
exports.resolveEnvPrefix = resolveEnvPrefix;
|
|
exports.searchForWorkspaceRoot = searchForWorkspaceRoot;
|
|
exports.send = send;
|
|
exports.splitVendorChunk = splitVendorChunk;
|
|
exports.splitVendorChunkPlugin = splitVendorChunkPlugin;
|
|
exports.version = VERSION;
|