Files

113 lines
3.8 KiB
JavaScript

import fs from "node:fs";
import path from "node:path";
import { normalizePath } from "vite";
const getConfigAlias = (settings) => {
const { tsConfig, tsConfigPath } = settings;
if (!tsConfig || !tsConfigPath || !tsConfig.compilerOptions) return null;
const { baseUrl, paths } = tsConfig.compilerOptions;
const effectiveBaseUrl = baseUrl ?? (paths ? "." : void 0);
if (!effectiveBaseUrl) return null;
const resolvedBaseUrl = path.resolve(path.dirname(tsConfigPath), effectiveBaseUrl);
const aliases = [];
if (paths) {
for (const [alias, values] of Object.entries(paths)) {
const find = new RegExp(
`^${[...alias].map(
(segment) => segment === "*" ? "(.+)" : segment.replace(/[\\^$*+?.()|[\]{}]/, "\\$&")
).join("")}$`
);
for (const value of values) {
let matchId = 0;
const replacement = [...normalizePath(path.resolve(resolvedBaseUrl, value))].map((segment) => segment === "*" ? `$${++matchId}` : segment === "$" ? "$$" : segment).join("");
aliases.push({ find, replacement });
}
}
}
if (baseUrl) {
aliases.push({
find: /^(?!\.*\/|\.*$|\w:)(.+)$/,
replacement: `${[...normalizePath(resolvedBaseUrl)].map((segment) => segment === "$" ? "$$" : segment).join("")}/$1`
});
}
return aliases;
};
const getViteResolveAlias = (settings) => {
const { tsConfig, tsConfigPath } = settings;
if (!tsConfig || !tsConfigPath || !tsConfig.compilerOptions) return [];
const { baseUrl, paths } = tsConfig.compilerOptions;
const effectiveBaseUrl = baseUrl ?? (paths ? "." : void 0);
if (!effectiveBaseUrl) return [];
const resolvedBaseUrl = path.resolve(path.dirname(tsConfigPath), effectiveBaseUrl);
const aliases = [];
if (paths) {
for (const [aliasPattern, values] of Object.entries(paths)) {
const resolvedValues = values.map((v) => path.resolve(resolvedBaseUrl, v));
const customResolver = (id) => {
for (const resolvedValue of resolvedValues) {
const resolved = resolvedValue.replace("*", id);
const stats = fs.statSync(resolved, { throwIfNoEntry: false });
if (stats && stats.isFile()) {
return normalizePath(resolved);
}
}
return null;
};
aliases.push({
// Build regex from alias pattern (e.g., '@styles/*' -> /^@styles\/(.+)$/)
// First, escape special regex chars. Then replace * with a capture group (.+)
find: new RegExp(
`^${aliasPattern.replace(/[\\^$+?.()|[\]{}]/g, "\\$&").replace(/\*/g, "(.+)")}$`
),
replacement: aliasPattern.includes("*") ? "$1" : aliasPattern,
customResolver
});
}
}
return aliases;
};
function configAliasVitePlugin({
settings
}) {
const configAlias = getConfigAlias(settings);
if (!configAlias) return null;
const plugin = {
name: "astro:tsconfig-alias",
// use post to only resolve ids that all other plugins before it can't
enforce: "post",
config() {
return {
resolve: {
alias: getViteResolveAlias(settings)
}
};
},
resolveId: {
filter: {
id: {
include: configAlias.map((alias) => alias.find),
exclude: /(?:\0|^virtual:|^astro:)/
}
},
async handler(id, importer, options) {
for (const alias of configAlias) {
if (alias.find.test(id)) {
const updatedId = id.replace(alias.find, alias.replacement);
if (updatedId.includes("*")) {
return updatedId;
}
const resolved = await this.resolve(updatedId, importer, {
skipSelf: true,
...options
});
if (resolved) return resolved;
}
}
}
}
};
return plugin;
}
export {
configAliasVitePlugin as default
};