@nestjs/schematics
Version:
Nest - modern, fast, powerful node.js web framework (@schematics)
115 lines (114 loc) • 5.07 kB
JavaScript
import { JSONFile } from '../../../utils/json-file.util.js';
import { findNestCliConfigPath, readJsonFile, readPackageJson, } from '../upgrade.utils.js';
const RSPACK_MIGRATION_URL = 'https://rspack.dev/guide/migration/webpack';
export function migrateCliConfig(report) {
return (tree) => {
const configPaths = [];
const cliConfigPath = findNestCliConfigPath(tree);
if (cliConfigPath) {
configPaths.push(...migrateNestCliJson(tree, cliConfigPath, report));
}
configPaths.push(...migrateScripts(tree, report));
if (configPaths.length > 0) {
report.action(`Port the webpack configuration file(s) ${[...new Set(configPaths)]
.map((path) => `"${path}"`)
.join(', ')} to Rspack (the API is largely compatible; see ${RSPACK_MIGRATION_URL}). ` +
'Replace "webpack" imports with "@rspack/core" and drop webpack-only plugins/loaders (e.g. "ts-loader" is not needed with Rspack\'s built-in SWC loader).');
}
return tree;
};
}
function migrateNestCliJson(tree, path, report) {
const config = readJsonFile(tree, path);
if (!config) {
return [];
}
const json = new JSONFile(tree, path);
const configPaths = [];
const targets = [
{
label: 'compilerOptions',
jsonPath: ['compilerOptions'],
options: config.compilerOptions,
},
];
for (const [name, project] of Object.entries(config.projects ?? {})) {
targets.push({
label: `projects.${name}.compilerOptions`,
jsonPath: ['projects', name, 'compilerOptions'],
options: project?.compilerOptions,
});
}
for (const { label, jsonPath, options } of targets) {
if (!options || typeof options !== 'object') {
continue;
}
const usesWebpack = options.webpack === true;
const webpackConfigPath = typeof options.webpackConfigPath === 'string'
? options.webpackConfigPath
: undefined;
const builder = options.builder;
const builderType = typeof builder === 'string' ? builder : builder?.type;
const builderConfigPath = typeof builder === 'object' ? builder?.options?.configPath : undefined;
if (!usesWebpack &&
webpackConfigPath === undefined &&
options.webpack === undefined &&
builderType !== 'webpack') {
continue;
}
if (usesWebpack ||
webpackConfigPath !== undefined ||
builderType === 'webpack') {
const configPath = builderConfigPath ?? webpackConfigPath;
const newBuilder = configPath
? { type: 'rspack', options: { configPath } }
: 'rspack';
if (builderType === 'webpack' ||
(usesWebpack && builderType === undefined) ||
(webpackConfigPath !== undefined && builderType === undefined)) {
json.modify([...jsonPath, 'builder'], newBuilder);
report.change(`${path}: ${label}.builder set to ${JSON.stringify(newBuilder)} (webpack is deprecated in favour of Rspack)`);
if (configPath) {
configPaths.push(configPath);
}
}
else if (usesWebpack || webpackConfigPath !== undefined) {
report.note(`${path}: ${label} already defines "builder" (${JSON.stringify(builderType)}); removed the deprecated "webpack"/"webpackConfigPath" options.`);
}
}
if (options.webpack !== undefined) {
json.remove([...jsonPath, 'webpack']);
if (!usesWebpack) {
report.change(`${path}: removed the deprecated "${label}.webpack: false" option`);
}
}
if (webpackConfigPath !== undefined) {
json.remove([...jsonPath, 'webpackConfigPath']);
}
}
return configPaths;
}
function migrateScripts(tree, report) {
const packageJson = readPackageJson(tree);
const scripts = packageJson?.scripts ?? {};
const configPaths = [];
const json = new JSONFile(tree, '/package.json');
for (const [name, script] of Object.entries(scripts)) {
if (typeof script !== 'string' ||
!/--webpack|--builder[ =]webpack|-b webpack/.test(script)) {
continue;
}
let updated = script;
updated = updated.replace(/--webpackPath(?:=|\s+)(\S+)/g, (_match, configPath) => {
configPaths.push(configPath.replace(/^['"]|['"]$/g, ''));
return `--rspackPath ${configPath}`;
});
updated = updated.replace(/--builder[ =]webpack\b|-b webpack\b/g, '--builder rspack');
updated = updated.replace(/--webpack\b(?!Path)/g, '--builder rspack');
if (updated !== script) {
json.modify(['scripts', name], updated);
report.change(`package.json: updated the "${name}" script to use Rspack ("${updated}")`);
}
}
return configPaths;
}