"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.crawlDir = exports.emptyDir = exports.writeFile = exports.generateCodeFrame = exports.numberToPos = exports.posToNumber = exports.pad = exports.lookupFile = exports.isObject = exports.prettifyUrl = exports.timeFrom = exports.asyncReplace = exports.removeTimestampQuery = exports.injectQuery = exports.removeImportQuery = exports.isImportRequest = exports.isJSRequest = exports.isDataUrl = exports.isExternalUrl = exports.cleanUrl = exports.hashRE = exports.queryRE = exports.fsPathFromId = exports.normalizePath = exports.createDebugger = exports.resolveFrom = exports.deepImportRE = exports.bareImportRE = void 0;
const debug_1 = __importDefault(require("debug"));
const chalk_1 = __importDefault(require("chalk"));
const fs_1 = __importDefault(require("fs"));
const os_1 = __importDefault(require("os"));
const path_1 = __importDefault(require("path"));
const url_1 = require("url");
const slash_1 = __importDefault(require("slash"));
const constants_1 = require("./constants");
const resolve_1 = __importDefault(require("resolve"));
exports.bareImportRE = /^[\w@]/;
exports.deepImportRE = /^([^@][^/]*)\/|^(@[^/]+\/[^/]+)\//;
let isRunningWithYarnPnp;
try {
    isRunningWithYarnPnp = Boolean(require('pnpapi'));
}
catch { }
function resolveFrom(id, basedir) {
    return resolve_1.default.sync(id, {
        basedir,
        extensions: constants_1.SUPPORTED_EXTS,
        // necessary to work with pnpm
        preserveSymlinks: isRunningWithYarnPnp || false
    });
}
exports.resolveFrom = resolveFrom;
// set in bin/vite.js
const filter = process.env.VITE_DEBUG_FILTER;
const DEBUG = process.env.DEBUG;
function createDebugger(ns, options = {}) {
    const log = debug_1.default(ns);
    const { onlyWhenFocused } = options;
    const focus = typeof onlyWhenFocused === 'string' ? onlyWhenFocused : ns;
    return (msg, ...args) => {
        if (filter && !msg.includes(filter)) {
            return;
        }
        if (onlyWhenFocused && !(DEBUG === null || DEBUG === void 0 ? void 0 : DEBUG.includes(focus))) {
            return;
        }
        log(msg, ...args);
    };
}
exports.createDebugger = createDebugger;
const isWindows = os_1.default.platform() === 'win32';
const VOLUME_RE = /^[A-Z]:/i;
function normalizePath(id) {
    if (isWindows) {
        return path_1.default.posix.normalize(slash_1.default(id.replace(VOLUME_RE, '')));
    }
    return path_1.default.posix.normalize(id);
}
exports.normalizePath = normalizePath;
function fsPathFromId(id) {
    const fsPath = normalizePath(id.slice(constants_1.FS_PREFIX.length));
    return fsPath.startsWith('/') ? fsPath : `/${fsPath}`;
}
exports.fsPathFromId = fsPathFromId;
exports.queryRE = /\?.*$/;
exports.hashRE = /#.*$/;
exports.cleanUrl = (url) => url.replace(exports.hashRE, '').replace(exports.queryRE, '');
const externalRE = /^(https?:)?\/\//;
exports.isExternalUrl = (url) => externalRE.test(url);
const dataUrlRE = /^\s*data:/i;
exports.isDataUrl = (url) => dataUrlRE.test(url);
const knownJsSrcRE = /\.((j|t)sx?|mjs|vue)($|\?)/;
exports.isJSRequest = (url) => knownJsSrcRE.test(url) || (!path_1.default.extname(url) && !url.endsWith('/'));
const importQueryRE = /(\?|&)import(&|$)/;
exports.isImportRequest = (url) => importQueryRE.test(url);
function removeImportQuery(url) {
    return url.replace(importQueryRE, '$1').replace(/\?$/, '');
}
exports.removeImportQuery = removeImportQuery;
function injectQuery(url, queryToInject) {
    const { pathname, search, hash } = url_1.parse(url);
    return `${pathname}?${queryToInject}${search ? `&` + search.slice(1) : ''}${hash || ''}`;
}
exports.injectQuery = injectQuery;
function removeTimestampQuery(url) {
    return url.replace(/\bt=\d{13}&?\b/, '').replace(/\?$/, '');
}
exports.removeTimestampQuery = removeTimestampQuery;
async function asyncReplace(input, re, replacer) {
    let match;
    let remaining = input;
    let rewritten = '';
    while ((match = re.exec(remaining))) {
        rewritten += remaining.slice(0, match.index);
        rewritten += await replacer(match);
        remaining = remaining.slice(match.index + match[0].length);
    }
    rewritten += remaining;
    return rewritten;
}
exports.asyncReplace = asyncReplace;
function timeFrom(start, subtract = 0) {
    const time = Date.now() - start - subtract;
    const timeString = (time + `ms`).padEnd(5, ' ');
    if (time < 10) {
        return chalk_1.default.green(timeString);
    }
    else if (time < 50) {
        return chalk_1.default.yellow(timeString);
    }
    else {
        return chalk_1.default.red(timeString);
    }
}
exports.timeFrom = timeFrom;
/**
 * pretty url for logging.
 */
function prettifyUrl(url, root) {
    url = removeTimestampQuery(url);
    const isAbsoluteFile = url.startsWith(root);
    if (isAbsoluteFile || url.startsWith(constants_1.FS_PREFIX)) {
        let file = path_1.default.relative(root, isAbsoluteFile ? url : url.slice(constants_1.FS_PREFIX.length));
        const seg = file.split('/');
        const npmIndex = seg.indexOf(`node_modules`);
        const isSourceMap = file.endsWith('.map');
        if (npmIndex > 0) {
            file = seg[npmIndex + 1];
            if (file.startsWith('@')) {
                file = `${file}/${seg[npmIndex + 2]}`;
            }
            file = `npm: ${chalk_1.default.dim(file)}${isSourceMap ? ` (source map)` : ``}`;
        }
        return chalk_1.default.dim(file);
    }
    else {
        return chalk_1.default.dim(url);
    }
}
exports.prettifyUrl = prettifyUrl;
function isObject(value) {
    return Object.prototype.toString.call(value) === '[object Object]';
}
exports.isObject = isObject;
function lookupFile(dir, formats, pathOnly = false) {
    for (const format of formats) {
        const fullPath = path_1.default.join(dir, format);
        if (fs_1.default.existsSync(fullPath) && fs_1.default.statSync(fullPath).isFile()) {
            return pathOnly ? fullPath : fs_1.default.readFileSync(fullPath, 'utf-8');
        }
    }
    const parentDir = path_1.default.dirname(dir);
    if (parentDir !== dir) {
        return lookupFile(parentDir, formats, pathOnly);
    }
}
exports.lookupFile = lookupFile;
const splitRE = /\r?\n/;
const range = 2;
function pad(source, n = 2) {
    const lines = source.split(splitRE);
    return lines.map((l) => ` `.repeat(n) + l).join(`\n`);
}
exports.pad = pad;
function posToNumber(source, pos) {
    if (typeof pos === 'number')
        return pos;
    const lines = source.split(splitRE);
    const { line, column } = pos;
    let start = 0;
    for (let i = 0; i < line - 1; i++) {
        start += lines[i].length;
    }
    return start + column;
}
exports.posToNumber = posToNumber;
function numberToPos(source, offset) {
    if (typeof offset !== 'number')
        return offset;
    if (offset > source.length) {
        throw new Error('offset is longer than source length!');
    }
    const lines = source.split(splitRE);
    let counted = 0;
    let line = 0;
    let column = 0;
    for (; line < lines.length; line++) {
        const lineLength = lines[line].length + 1;
        if (counted + lineLength >= offset) {
            column = offset - counted + 1;
            break;
        }
        counted += lineLength;
    }
    return { line: line + 1, column };
}
exports.numberToPos = numberToPos;
function generateCodeFrame(source, start = 0, end) {
    start = posToNumber(source, start);
    end = end || start;
    const lines = source.split(splitRE);
    let count = 0;
    const res = [];
    for (let i = 0; i < lines.length; i++) {
        count += lines[i].length + 1;
        if (count >= start) {
            for (let j = i - range; j <= i + range || end > count; j++) {
                if (j < 0 || j >= lines.length)
                    continue;
                const line = j + 1;
                res.push(`${line}${' '.repeat(Math.max(3 - String(line).length, 0))}|  ${lines[j]}`);
                const lineLength = lines[j].length;
                if (j === i) {
                    // push underline
                    const pad = start - (count - lineLength) + 1;
                    const length = Math.max(1, end > count ? lineLength - pad : end - start);
                    res.push(`   |  ` + ' '.repeat(pad) + '^'.repeat(length));
                }
                else if (j > i) {
                    if (end > count) {
                        const length = Math.max(Math.min(end - count, lineLength), 1);
                        res.push(`   |  ` + '^'.repeat(length));
                    }
                    count += lineLength + 1;
                }
            }
            break;
        }
    }
    return res.join('\n');
}
exports.generateCodeFrame = generateCodeFrame;
function writeFile(filename, content) {
    const dir = path_1.default.dirname(filename);
    if (!fs_1.default.existsSync(dir)) {
        fs_1.default.mkdirSync(dir, { recursive: true });
    }
    fs_1.default.writeFileSync(filename, content);
}
exports.writeFile = writeFile;
function emptyDir(dir) {
    if (!fs_1.default.existsSync(dir)) {
        return;
    }
    for (const file of fs_1.default.readdirSync(dir)) {
        const abs = path_1.default.resolve(dir, file);
        // baseline is Node 12 so can't use rmSync :(
        if (fs_1.default.lstatSync(abs).isDirectory()) {
            emptyDir(abs);
            fs_1.default.rmdirSync(abs);
        }
        else {
            fs_1.default.unlinkSync(abs);
        }
    }
}
exports.emptyDir = emptyDir;
function crawlDir(root, onFile) {
    const recurse = (parent) => fs_1.default.readdirSync(path_1.default.join(root, parent)).forEach((name) => {
        const child = path_1.default.join(parent, name);
        const stat = fs_1.default.statSync(path_1.default.join(root, child));
        if (stat.isDirectory()) {
            recurse(child);
        }
        else {
            onFile(child, name, parent);
        }
    });
    recurse('');
}
exports.crawlDir = crawlDir;
//# sourceMappingURL=utils.js.map