335 lines
8.3 KiB
Plaintext
335 lines
8.3 KiB
Plaintext
import { resolve, join, parse, dirname, isAbsolute } from "node:path";
|
|
import figlet from "figlet";
|
|
import { normalizePath, version } from "vite";
|
|
import picocolors from "picocolors";
|
|
import crypto from "node:crypto";
|
|
import { inspect } from "node:util";
|
|
import { LogFactory, Level, PatternLayout } from "base-log-factory";
|
|
import { DebugAppender } from "blf-debug-appender";
|
|
import { readFileSync, statSync } from "node:fs";
|
|
const colorful = {};
|
|
Object.entries(picocolors).forEach(([key, value]) => {
|
|
colorful[key] = (text) => {
|
|
console.log(value(text));
|
|
};
|
|
});
|
|
const hash = crypto.hash ?? ((algorithm, data, outputEncoding) => crypto.createHash(algorithm).update(data).digest(outputEncoding));
|
|
function getHash(text, length = 8) {
|
|
const h = hash("sha256", text, "hex").substring(0, length);
|
|
if (length <= 64) {
|
|
return h;
|
|
}
|
|
return h.padEnd(length, "_");
|
|
}
|
|
function getDepsCacheSuffix(config, ssr) {
|
|
let suffix = "";
|
|
if (config.command === "build") {
|
|
const { outDir } = config.build;
|
|
const buildId = outDir.length > 8 || outDir.includes("/") ? getHash(outDir) : outDir;
|
|
suffix += `_build-${buildId}`;
|
|
}
|
|
if (ssr) {
|
|
suffix += "_ssr";
|
|
}
|
|
return suffix;
|
|
}
|
|
function getDepsCacheDirPrefix(config) {
|
|
return normalizePath(resolve(config.cacheDir, "deps"));
|
|
}
|
|
function getDepsCacheDir(config, ssr) {
|
|
return getDepsCacheDirPrefix(config) + getDepsCacheSuffix(config, ssr);
|
|
}
|
|
const FLATTEN_ID_HASH_LENGTH = 8;
|
|
const FLATTEN_ID_MAX_FILE_LENGTH = 170;
|
|
const limitFlattenIdLength = (id, limit = FLATTEN_ID_MAX_FILE_LENGTH) => {
|
|
if (id.length <= limit) {
|
|
return id;
|
|
}
|
|
return `${id.slice(0, limit - (FLATTEN_ID_HASH_LENGTH + 1))}_${getHash(id)}`;
|
|
};
|
|
const replaceSlashOrColonRE = /[/:]/g;
|
|
const replaceDotRE = /\./g;
|
|
const replaceNestedIdRE = /\s*>\s*/g;
|
|
const replaceHashRE = /#/g;
|
|
function flattenId(id) {
|
|
const flatId = limitFlattenIdLength(id.replace(replaceSlashOrColonRE, "_").replace(replaceDotRE, "__").replace(replaceNestedIdRE, "___").replace(replaceHashRE, "____"));
|
|
return flatId;
|
|
}
|
|
function isDevServer(server) {
|
|
return "pluginContainer" in server;
|
|
}
|
|
const VOLUME_RE = /^[A-Z]:/i;
|
|
const FS_PREFIX = "/@fs/";
|
|
function fsPathFromId(id) {
|
|
const fsPath = normalizePath(id.startsWith(FS_PREFIX) ? id.slice(FS_PREFIX.length) : id);
|
|
return fsPath.startsWith("/") || VOLUME_RE.test(fsPath) ? fsPath : `/${fsPath}`;
|
|
}
|
|
const postfixRE = /[?#].*$/;
|
|
function cleanUrl(url) {
|
|
return url.replace(postfixRE, "");
|
|
}
|
|
function toPath(deepKey) {
|
|
const result = [];
|
|
const length = deepKey.length;
|
|
if (length === 0) {
|
|
return result;
|
|
}
|
|
let index = 0;
|
|
let key = "";
|
|
let quoteChar = "";
|
|
let bracket = false;
|
|
if (deepKey.charCodeAt(0) === 46) {
|
|
result.push("");
|
|
index++;
|
|
}
|
|
while (index < length) {
|
|
const char = deepKey[index];
|
|
if (quoteChar) {
|
|
if (char === "\\" && index + 1 < length) {
|
|
index++;
|
|
key += deepKey[index];
|
|
} else if (char === quoteChar) {
|
|
quoteChar = "";
|
|
} else {
|
|
key += char;
|
|
}
|
|
} else if (bracket) {
|
|
if (char === '"' || char === "'") {
|
|
quoteChar = char;
|
|
} else if (char === "]") {
|
|
bracket = false;
|
|
result.push(key);
|
|
key = "";
|
|
} else {
|
|
key += char;
|
|
}
|
|
} else if (char === "[") {
|
|
bracket = true;
|
|
if (key) {
|
|
result.push(key);
|
|
key = "";
|
|
}
|
|
} else if (char === ".") {
|
|
if (key) {
|
|
result.push(key);
|
|
key = "";
|
|
}
|
|
} else {
|
|
key += char;
|
|
}
|
|
index++;
|
|
}
|
|
if (key) {
|
|
result.push(key);
|
|
}
|
|
return result;
|
|
}
|
|
function toKey(value) {
|
|
const whatType = typeof value;
|
|
if (whatType === "string" || whatType === "symbol") {
|
|
return value;
|
|
}
|
|
if (Object.is(value.valueOf(), -0)) {
|
|
return "-0";
|
|
}
|
|
return value.toString();
|
|
}
|
|
function isDeepKey(key) {
|
|
switch (typeof key) {
|
|
case "number":
|
|
case "symbol": {
|
|
return false;
|
|
}
|
|
case "string": {
|
|
return key.includes(".") || key.includes("[") || key.includes("]");
|
|
}
|
|
}
|
|
}
|
|
function getWithPath(object, path, defaultValue) {
|
|
if (path.length === 0 || object == null) {
|
|
return defaultValue;
|
|
}
|
|
const lastIndex = path.length - 1;
|
|
let lastObject = object;
|
|
let current = null;
|
|
let cursor = 0;
|
|
for (let prevPath; cursor <= lastIndex; cursor++) {
|
|
prevPath = path[cursor];
|
|
current = lastObject[prevPath];
|
|
if (current == null) {
|
|
current = cursor === lastIndex ? defaultValue : typeof prevPath === "number" ? [] : {};
|
|
lastObject[prevPath] = current;
|
|
}
|
|
lastObject = current;
|
|
}
|
|
return current;
|
|
}
|
|
function getValue(object, path, defaultValue) {
|
|
if (object == null) {
|
|
return defaultValue;
|
|
}
|
|
switch (typeof path) {
|
|
case "string": {
|
|
const result = object[path];
|
|
if (result === void 0) {
|
|
if (isDeepKey(path)) {
|
|
return getValue(object, toPath(path), defaultValue);
|
|
}
|
|
object[path] = defaultValue;
|
|
return defaultValue;
|
|
}
|
|
return result;
|
|
}
|
|
case "number":
|
|
case "symbol": {
|
|
if (typeof path === "number") {
|
|
path = toKey(path);
|
|
}
|
|
const result = object[path];
|
|
if (result === void 0) {
|
|
object[path] = defaultValue;
|
|
return defaultValue;
|
|
}
|
|
return result;
|
|
}
|
|
default: {
|
|
if (Array.isArray(path)) {
|
|
return getWithPath(object, path, defaultValue);
|
|
}
|
|
if (Object.is(path == null ? void 0 : path.valueOf(), -0)) {
|
|
path = "-0";
|
|
} else {
|
|
path = String(path);
|
|
}
|
|
const result = object[path];
|
|
if (result === void 0) {
|
|
object[path] = defaultValue;
|
|
return defaultValue;
|
|
}
|
|
return result;
|
|
}
|
|
}
|
|
}
|
|
function createConverter(specifier) {
|
|
if (specifier === "m") {
|
|
return (event) => {
|
|
return event.message.map((msg) => {
|
|
switch (typeof msg) {
|
|
case "object":
|
|
return inspect(msg);
|
|
case "symbol":
|
|
return msg.toString();
|
|
default:
|
|
return msg;
|
|
}
|
|
}).join(" ");
|
|
};
|
|
}
|
|
}
|
|
const logFactory = new LogFactory({
|
|
level: Level.WARN,
|
|
appenders: [
|
|
new DebugAppender({
|
|
layout: new PatternLayout("%d{HH:mm:ss} [%p] - %m", createConverter)
|
|
})
|
|
]
|
|
});
|
|
function displayTime(time) {
|
|
if (time < 1e3) {
|
|
return `${time}ms`;
|
|
}
|
|
time = time / 1e3;
|
|
if (time < 60) {
|
|
return `${time.toFixed(2)}s`;
|
|
}
|
|
const mins = Math.floor(time / 60);
|
|
const seconds = Math.round(time % 60);
|
|
if (seconds === 60) {
|
|
return `${mins + 1}m`;
|
|
}
|
|
return `${mins}m${seconds < 1 ? "" : ` ${seconds}s`}`;
|
|
}
|
|
function getClosestFilePath(fileName, path) {
|
|
if (!path) {
|
|
path = process.cwd();
|
|
}
|
|
const pathObj = parse(path);
|
|
if (pathObj.root === path) {
|
|
return null;
|
|
}
|
|
try {
|
|
const state = statSync(path);
|
|
if (state.isDirectory()) {
|
|
const filePath = join(path, fileName);
|
|
try {
|
|
if (!statSync(filePath).isDirectory()) {
|
|
return filePath;
|
|
}
|
|
} catch (e) {
|
|
if (e.code === "ENOENT") {
|
|
return getClosestFilePath(fileName, join(path, ".."));
|
|
}
|
|
return null;
|
|
}
|
|
return getClosestFilePath(fileName, join(path, ".."));
|
|
}
|
|
return getClosestFilePath(fileName, dirname(path));
|
|
} catch (e) {
|
|
return null;
|
|
}
|
|
}
|
|
function getClosestPkg(path) {
|
|
const filePath = getClosestFilePath("package.json", path);
|
|
if (filePath) {
|
|
const pkg = readFileSync(filePath, "utf-8");
|
|
return JSON.parse(pkg);
|
|
}
|
|
return null;
|
|
}
|
|
function getRuntimeVersion() {
|
|
const { argv } = process;
|
|
let vitePath = argv[1];
|
|
if (!/(\\|\/)vite(\\|\/)/.test(vitePath)) {
|
|
vitePath = join(process.cwd(), "node_modules", "vite");
|
|
}
|
|
const pkg = getClosestPkg(vitePath);
|
|
return pkg ? pkg.version : version;
|
|
}
|
|
const escapeRegexRE = /[-/\\^$*+?.()|[\]{}]/g;
|
|
function escapeRegex(str) {
|
|
return str.replace(escapeRegexRE, "\\$&");
|
|
}
|
|
function banner(text, opts) {
|
|
console.log(figlet.textSync(text, opts));
|
|
}
|
|
function toAbsolutePath(pth, cwd) {
|
|
if (!isAbsolute(pth)) {
|
|
pth = join(cwd, pth);
|
|
}
|
|
return normalizePath(pth);
|
|
}
|
|
function sleep(ms) {
|
|
return new Promise((resolve2) => {
|
|
setTimeout(resolve2, ms);
|
|
});
|
|
}
|
|
export {
|
|
FS_PREFIX,
|
|
banner,
|
|
cleanUrl,
|
|
colorful,
|
|
displayTime,
|
|
escapeRegex,
|
|
flattenId,
|
|
fsPathFromId,
|
|
getDepsCacheDir,
|
|
getHash,
|
|
getRuntimeVersion,
|
|
getValue,
|
|
isDeepKey,
|
|
isDevServer,
|
|
logFactory,
|
|
sleep,
|
|
toAbsolutePath
|
|
};
|