"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __setModuleDefault(result, mod);
    return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.urlToBuiltUrl = exports.fileToUrl = exports.checkPublicFile = exports.checkPublicFiles = exports.assetPlugin = exports.assetUrlRE = void 0;
const path_1 = __importDefault(require("path"));
const url_1 = require("url");
const fs_1 = __importStar(require("fs"));
const lite_1 = __importDefault(require("mime/lite"));
const utils_1 = require("../utils");
const constants_1 = require("../constants");
const magic_string_1 = __importDefault(require("magic-string"));
exports.assetUrlRE = /"__VITE_ASSET__(\w+)(?:__(.*)__)?"/g;
/**
 * Also supports loading plain strings with import text from './foo.txt?raw'
 */
function assetPlugin(config) {
    return {
        name: 'vite:asset',
        resolveId(id) {
            if (!config.assetsInclude(utils_1.cleanUrl(id))) {
                return;
            }
            // imports to absolute urls pointing to files in /public
            // will fail to resolve in the main resolver. handle them here.
            const publicFile = checkPublicFile(id, config.root);
            if (publicFile) {
                return id;
            }
        },
        async load(id) {
            if (!config.assetsInclude(utils_1.cleanUrl(id))) {
                return;
            }
            // raw requests, read from disk
            if (/(\?|&)raw\b/.test(id)) {
                const file = checkPublicFile(id, config.root) || utils_1.cleanUrl(id);
                // raw query, read file and return as string
                return `export default ${JSON.stringify(await fs_1.promises.readFile(file, 'utf-8'))}`;
            }
            const url = await fileToUrl(id, config, this);
            return `export default ${JSON.stringify(url)}`;
        },
        renderChunk(code) {
            let match;
            let s;
            while ((match = exports.assetUrlRE.exec(code))) {
                s = s || (s = new magic_string_1.default(code));
                const [full, fileHandle, postfix = ''] = match;
                const outputFilepath = config.build.base + this.getFileName(fileHandle) + postfix;
                s.overwrite(match.index, match.index + full.length, JSON.stringify(outputFilepath));
            }
            if (s) {
                return {
                    code: s.toString(),
                    map: config.build.sourcemap ? s.generateMap({ hires: true }) : null
                };
            }
            else {
                return null;
            }
        }
    };
}
exports.assetPlugin = assetPlugin;
function checkPublicFiles(root) {
    const get = (_, file) => checkPublicFile(file, root) && file;
    return new Proxy({}, { get });
}
exports.checkPublicFiles = checkPublicFiles;
function checkPublicFile(url, root) {
    // note if the file is in /public, the resolver would have returned it
    // as-is so it's not going to be a fully resolved path.
    if (!url.startsWith('/')) {
        return;
    }
    const publicFile = path_1.default.posix.join(root, 'public', utils_1.cleanUrl(url));
    if (fs_1.default.existsSync(publicFile)) {
        return publicFile;
    }
    else {
        return;
    }
}
exports.checkPublicFile = checkPublicFile;
function fileToUrl(id, config, ctx) {
    if (config.command === 'serve') {
        return fileToDevUrl(id, config);
    }
    else {
        return fileToBuiltUrl(id, config, ctx);
    }
}
exports.fileToUrl = fileToUrl;
function fileToDevUrl(id, { root }) {
    if (checkPublicFile(id, root)) {
        // in public dir, keep the url as-is
        return id;
    }
    if (id.startsWith(root)) {
        // in project root, infer short public path
        return '/' + path_1.default.posix.relative(root, id);
    }
    // outside of project root, use absolute fs path
    // (this is speical handled by the serve static middleware
    return constants_1.FS_PREFIX + id;
}
const assetCache = new WeakMap();
/**
 * Register an asset to be emitted as part of the bundle (if necessary)
 * and returns the resolved public URL
 */
async function fileToBuiltUrl(id, config, pluginContext, skipPublicCheck = false) {
    const publicUrl = !skipPublicCheck && config.publicUrls[id];
    if (publicUrl) {
        return config.build.base + publicUrl.slice(1);
    }
    let cache = assetCache.get(config);
    if (!cache) {
        cache = new Map();
        assetCache.set(config, cache);
    }
    const cached = cache.get(id);
    if (cached) {
        return cached;
    }
    const file = utils_1.cleanUrl(id);
    const { search, hash } = url_1.parse(id);
    const postfix = (search || '') + (hash || '');
    // TODO preserve fragment hash or queries
    const content = await fs_1.promises.readFile(file);
    let url;
    if (config.build.lib ||
        (!file.endsWith('.svg') &&
            content.length < Number(config.build.assetsInlineLimit))) {
        // base64 inlined as a string
        url = `data:${lite_1.default.getType(file)};base64,${content.toString('base64')}`;
    }
    else {
        // emit as asset
        // rollup supports `import.meta.ROLLUP_FILE_URL_*`, but it generates code
        // that uses runtime url sniffing and it can be verbose when targeting
        // non-module format. For consistency, generate a marker here and replace
        // with resolved url strings in renderChunk.
        const fileId = pluginContext.emitFile({
            name: path_1.default.basename(file),
            type: 'asset',
            source: content
        });
        url = `__VITE_ASSET__${fileId}${postfix ? `__${postfix}__` : ``}`;
    }
    cache.set(id, url);
    return url;
}
async function urlToBuiltUrl(url, importer, config, pluginContext) {
    const publicUrl = config.publicUrls[url];
    if (publicUrl) {
        return config.build.base + publicUrl.slice(1);
    }
    const file = url.startsWith('/')
        ? path_1.default.join(config.root, url)
        : path_1.default.join(path_1.default.dirname(importer), url);
    return fileToBuiltUrl(file, config, pluginContext, 
    // skip public check since we just did it above
    true);
}
exports.urlToBuiltUrl = urlToBuiltUrl;
//# sourceMappingURL=asset.js.map