@nx/vite
Version:
177 lines (176 loc) • 9.23 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.nxViteTsPaths = nxViteTsPaths;
const devkit_1 = require("@nx/devkit");
const node_fs_1 = require("node:fs");
const node_path_1 = require("node:path");
const tsconfig_paths_1 = require("tsconfig-paths");
const buildable_libs_utils_1 = require("@nx/js/src/utils/buildable-libs-utils");
const nx_vite_build_coordination_plugin_1 = require("./nx-vite-build-coordination.plugin");
const nx_tsconfig_paths_find_file_1 = require("../src/utils/nx-tsconfig-paths-find-file");
const ts_solution_setup_1 = require("@nx/js/src/utils/typescript/ts-solution-setup");
const options_utils_1 = require("../src/utils/options-utils");
function nxViteTsPaths(options = {}) {
let foundTsConfigPath;
let matchTsPathEsm;
let matchTsPathFallback;
let tsConfigPathsEsm;
let tsConfigPathsFallback;
options.extensions ??= [
'.ts',
'.tsx',
'.js',
'.jsx',
'.json',
'.mts',
'.mjs',
'.cts',
'.cjs',
'.css',
'.scss',
'.less',
];
options.mainFields ??= [['exports', '.', 'import'], 'module', 'main'];
options.buildLibsFromSource ??= true;
let projectRoot = '';
return {
name: 'nx-vite-ts-paths',
// Ensure the resolveId aspect of the plugin is called before vite's internal resolver
// Otherwise, issues can arise with Yarn Workspaces and Pnpm Workspaces
enforce: 'pre',
async configResolved(config) {
projectRoot = config.root;
const projectRootFromWorkspaceRoot = (0, node_path_1.relative)(devkit_1.workspaceRoot, projectRoot);
foundTsConfigPath = getTsConfig(process.env.NX_TSCONFIG_PATH ??
(0, node_path_1.join)(devkit_1.workspaceRoot, 'tmp', projectRootFromWorkspaceRoot, process.env.NX_TASK_TARGET_TARGET ?? 'build', 'tsconfig.generated.json'));
if (!foundTsConfigPath)
return;
if (!options.buildLibsFromSource &&
!global.NX_GRAPH_CREATION &&
config.mode !== 'test') {
const projectGraph = await (0, devkit_1.createProjectGraphAsync)({
exitOnError: false,
resetDaemonClient: true,
});
// When using incremental building and the serve target is called
// we need to get the deps for the 'build' target instead.
const depsBuildTarget = process.env.NX_TASK_TARGET_TARGET === 'serve'
? 'build'
: process.env.NX_TASK_TARGET_TARGET;
const { dependencies } = (0, buildable_libs_utils_1.calculateProjectBuildableDependencies)(undefined, projectGraph, devkit_1.workspaceRoot, process.env.NX_TASK_TARGET_PROJECT, depsBuildTarget, process.env.NX_TASK_TARGET_CONFIGURATION);
// This tsconfig is used via the Vite ts paths plugin.
// It can be also used by other user-defined Vite plugins (e.g. for creating type declaration files).
foundTsConfigPath = (0, buildable_libs_utils_1.createTmpTsConfig)(foundTsConfigPath, devkit_1.workspaceRoot, (0, node_path_1.relative)(devkit_1.workspaceRoot, projectRoot), dependencies, true);
if (config.command === 'serve') {
const buildableLibraryDependencies = dependencies
.filter((dep) => dep.node.type === 'lib')
.map((dep) => dep.node.name)
.join(',');
const buildCommand = `npx nx run-many --target=${depsBuildTarget} --projects=${buildableLibraryDependencies}`;
config.plugins.push((0, nx_vite_build_coordination_plugin_1.nxViteBuildCoordinationPlugin)({ buildCommand }));
}
}
const parsed = (0, tsconfig_paths_1.loadConfig)(foundTsConfigPath);
logIt('first parsed tsconfig: ', parsed);
if (parsed.resultType === 'failed') {
throw new Error(`Failed loading tsconfig at ${foundTsConfigPath}`);
}
tsConfigPathsEsm = parsed;
matchTsPathEsm = (0, tsconfig_paths_1.createMatchPath)(parsed.absoluteBaseUrl, parsed.paths, options.mainFields);
const rootLevelTsConfig = getTsConfig((0, node_path_1.join)(devkit_1.workspaceRoot, 'tsconfig.base.json'));
const rootLevelParsed = (0, tsconfig_paths_1.loadConfig)(rootLevelTsConfig);
logIt('fallback parsed tsconfig: ', rootLevelParsed);
if (rootLevelParsed.resultType === 'success') {
tsConfigPathsFallback = rootLevelParsed;
matchTsPathFallback = (0, tsconfig_paths_1.createMatchPath)(rootLevelParsed.absoluteBaseUrl, rootLevelParsed.paths, ['main', 'module']);
}
},
resolveId(importPath) {
// Let other resolvers handle this path.
if (!foundTsConfigPath)
return null;
let resolvedFile;
try {
resolvedFile = matchTsPathEsm(importPath);
}
catch (e) {
logIt('Using fallback path matching.');
resolvedFile = matchTsPathFallback?.(importPath);
}
if (!resolvedFile || !(0, node_fs_1.existsSync)(resolvedFile)) {
if (tsConfigPathsEsm || tsConfigPathsFallback) {
logIt(`Unable to resolve ${importPath} with tsconfig paths. Using fallback file matching.`);
resolvedFile =
loadFileFromPaths(tsConfigPathsEsm, importPath) ||
loadFileFromPaths(tsConfigPathsFallback, importPath);
}
else {
logIt(`Unable to resolve ${importPath} with tsconfig paths`);
}
}
logIt(`Resolved ${importPath} to ${resolvedFile}`);
// Returning null defers to other resolveId functions and eventually the default resolution behavior
// https://rollupjs.org/plugin-development/#resolveid
return resolvedFile || null;
},
async writeBundle(options) {
if ((0, ts_solution_setup_1.isUsingTsSolutionSetup)())
return;
const outDir = options.dir || 'dist';
const src = (0, node_path_1.resolve)(projectRoot, 'package.json');
if ((0, node_fs_1.existsSync)(src)) {
const dest = (0, node_path_1.join)(outDir, 'package.json');
try {
(0, node_fs_1.copyFileSync)(src, dest);
}
catch (err) {
console.error('Error copying package.json:', err);
}
}
},
};
function getTsConfig(preferredTsConfigPath) {
const projectTsConfigPath = (0, options_utils_1.getProjectTsConfigPath)(projectRoot);
return [
(0, node_path_1.resolve)(preferredTsConfigPath),
projectTsConfigPath ? (0, node_path_1.resolve)(projectTsConfigPath) : null,
(0, node_path_1.resolve)((0, node_path_1.join)(devkit_1.workspaceRoot, 'tsconfig.base.json')),
(0, node_path_1.resolve)((0, node_path_1.join)(devkit_1.workspaceRoot, 'tsconfig.json')),
(0, node_path_1.resolve)((0, node_path_1.join)(devkit_1.workspaceRoot, 'jsconfig.json')),
]
.filter(Boolean)
.find((tsPath) => {
if ((0, node_fs_1.existsSync)(tsPath)) {
logIt('Found tsconfig at', tsPath);
return tsPath;
}
});
}
function logIt(...msg) {
if (process.env.NX_VERBOSE_LOGGING === 'true' && options?.debug !== false) {
console.debug('\n[Nx Vite TsPaths]', ...msg);
}
}
function loadFileFromPaths(tsconfig, importPath) {
logIt(`Trying to resolve file from config in ${tsconfig.configFileAbsolutePath}`);
let resolvedFile;
for (const alias in tsconfig.paths) {
const paths = tsconfig.paths[alias];
const normalizedImport = alias.replace(/\/\*$/, '');
if (importPath === normalizedImport ||
importPath.startsWith(normalizedImport + '/')) {
const joinedPath = (0, devkit_1.joinPathFragments)(tsconfig.absoluteBaseUrl, paths[0].replace(/\/\*$/, ''));
resolvedFile = (0, nx_tsconfig_paths_find_file_1.findFile)(importPath.replace(normalizedImport, joinedPath), options.extensions);
if (resolvedFile === undefined &&
options.extensions.some((ext) => importPath.endsWith(ext))) {
const foundExtension = options.extensions.find((ext) => importPath.endsWith(ext));
const pathWithoutExtension = importPath
.replace(normalizedImport, joinedPath)
.slice(0, -foundExtension.length);
resolvedFile = (0, nx_tsconfig_paths_find_file_1.findFile)(pathWithoutExtension, options.extensions);
}
}
}
return resolvedFile;
}
}
;