219 lines
7.6 KiB
JavaScript
Raw Normal View History

2026-05-31 13:21:13 +02:00
"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/index.ts
var src_exports = {};
__export(src_exports, {
DefaultRules: () => DefaultRules,
VitePluginRemoteAssets: () => VitePluginRemoteAssets,
default: () => src_default
});
module.exports = __toCommonJS(src_exports);
var import_node_path = require("path");
var import_utils = require("@antfu/utils");
var import_axios = __toESM(require("axios"), 1);
var import_blueimp_md5 = __toESM(require("blueimp-md5"), 1);
var import_debug = __toESM(require("debug"), 1);
var import_fs_extra = __toESM(require("fs-extra"), 1);
var import_magic_string = __toESM(require("magic-string"), 1);
var import_vite = require("vite");
var DefaultRules = [
{
match: /\b(https?:\/\/[\w#&?./-]*?\.(?:png|jpe?g|svg|ico))(?=[`'")\]])/gi
}
];
function isValidHttpUrl(str) {
let url;
try {
url = new URL(str);
} catch {
return false;
}
return url.protocol === "http:" || url.protocol === "https:";
}
function sleep(seconds) {
return new Promise((resolve2) => setTimeout(resolve2, seconds * 1e3));
}
var debug = (0, import_debug.default)("vite-plugin-remote-assets");
function VitePluginRemoteAssets(options = {}) {
const {
assetsDir = "node_modules/.remote-assets",
rules = DefaultRules,
resolveMode = "relative",
awaitDownload = true,
retryTooManyRequests = false
} = options;
let dir = void 0;
let config;
const envs = [];
async function downloadTo(url, filepath, { retryTooManyRequests: retryTooManyRequests2 }) {
const writer = import_fs_extra.default.createWriteStream(filepath);
const response = await (0, import_axios.default)({
url,
method: "GET",
validateStatus: (status) => {
if (status >= 200 && status < 300)
return true;
else if (retryTooManyRequests2 && status === 429)
return true;
else
return false;
},
responseType: "stream"
});
if (response.status === 429) {
const retryAfter = response.headers["retry-after"];
if (!retryAfter) {
throw new Error(`${url}: 429 without retry-after header`);
} else {
debug(`${url}: 429, retry after ${retryAfter} seconds`);
await sleep(retryAfter);
return await downloadTo(url, filepath, { retryTooManyRequests: retryTooManyRequests2 });
}
}
response.data.pipe(writer);
return new Promise((resolve2, reject) => {
writer.on("finish", resolve2);
writer.on("error", reject);
});
}
const tasksMap = {};
async function transform(code, id) {
const tasks = [];
const s = new import_magic_string.default(code);
let hasReplaced = false;
let match;
for (const rule of rules) {
rule.match.lastIndex = 0;
while (match = rule.match.exec(code)) {
const start = match.index;
const end = start + match[0].length;
const url = match[0];
if (!url || !isValidHttpUrl(url))
continue;
const hash = (0, import_blueimp_md5.default)(url) + (rule.ext || (0, import_node_path.extname)(url));
const filepath = (0, import_utils.slash)((0, import_node_path.resolve)(dir, hash));
debug("detected", url, hash);
if (!import_fs_extra.default.existsSync(filepath) || tasksMap[filepath]) {
if (!tasksMap[filepath]) {
tasksMap[filepath] = (async () => {
try {
debug("downloading", url);
await downloadTo(url, filepath, { retryTooManyRequests });
debug("downloaded", url);
} catch (e) {
if (import_fs_extra.default.existsSync(filepath))
await import_fs_extra.default.unlink(filepath);
throw e;
} finally {
delete tasksMap[filepath];
}
})();
}
tasks.push(tasksMap[filepath]);
if (!awaitDownload)
continue;
}
hasReplaced = true;
const mode = typeof resolveMode === "function" ? resolveMode(id, url) : resolveMode;
let newUrl;
if (mode === "relative") {
newUrl = (0, import_utils.slash)((0, import_node_path.relative)((0, import_node_path.dirname)(id), `${dir}/${hash}`));
if (newUrl[0] !== ".")
newUrl = `./${newUrl}`;
} else {
let path = `${dir}/${hash}`;
if (!path.startsWith("/"))
path = `/${path}`;
newUrl = `/@fs${path}`;
}
s.overwrite(start, end, newUrl);
}
}
if (tasks.length) {
if (awaitDownload) {
await Promise.all(tasks);
} else {
Promise.all(tasks).then(() => {
envs.forEach((env) => {
if (env instanceof import_vite.DevEnvironment) {
const module3 = env.moduleGraph.getModuleById(id);
if (module3)
env.moduleGraph.invalidateModule(module3);
return;
}
const module2 = env.moduleGraph.getModuleById(id);
if (module2)
env.moduleGraph.invalidateModule(module2);
});
});
}
}
if (!hasReplaced)
return null;
return {
code: s.toString(),
map: config.build.sourcemap ? s.generateMap({ hires: true }) : null
};
}
return {
name: "vite-plugin-remote-assets",
enforce: "pre",
async configResolved(_config) {
config = _config;
dir = (0, import_utils.slash)((0, import_node_path.resolve)(config.root, assetsDir));
if ("force" in config.server && config.server.force || config.optimizeDeps.force)
await import_fs_extra.default.emptyDir(dir);
await import_fs_extra.default.ensureDir(dir);
},
configureServer(server) {
if ("environments" in server && typeof server.environments === "object" && server.environments != null) {
Object.values(server.environments).forEach((env) => envs.push(env));
} else {
envs.push(server);
}
},
async transform(code, id) {
return await transform(code, id);
},
transformIndexHtml: {
order: "pre",
async handler(code, ctx) {
return (await transform(code, ctx.filename))?.code;
}
}
};
}
var src_default = VitePluginRemoteAssets;
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
DefaultRules,
VitePluginRemoteAssets
});