@nx/esbuild
Version:
182 lines (181 loc) • 7.89 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.configurationGenerator = configurationGenerator;
const devkit_1 = require("@nx/devkit");
const target_defaults_utils_1 = require("@nx/devkit/src/generators/target-defaults-utils");
const js_1 = require("@nx/js");
const get_import_path_1 = require("@nx/js/src/utils/get-import-path");
const ts_solution_setup_1 = require("@nx/js/src/utils/typescript/ts-solution-setup");
const posix_1 = require("node:path/posix");
const devkit_internals_1 = require("nx/src/devkit-internals");
const build_esbuild_options_1 = require("../../executors/esbuild/lib/build-esbuild-options");
const init_1 = require("../init/init");
async function configurationGenerator(tree, options) {
const task = await (0, init_1.esbuildInitGenerator)(tree, {
...options,
skipFormat: true,
});
options.buildTarget ??= 'build';
const isTsSolutionSetup = (0, ts_solution_setup_1.isUsingTsSolutionSetup)(tree);
checkForTargetConflicts(tree, options);
addBuildTarget(tree, options, isTsSolutionSetup);
updatePackageJson(tree, options, isTsSolutionSetup);
await (0, devkit_1.formatFiles)(tree);
return task;
}
function checkForTargetConflicts(tree, options) {
if (options.skipValidation)
return;
const project = (0, devkit_1.readProjectConfiguration)(tree, options.project);
if (project.targets?.[options.buildTarget]) {
throw new Error(`Project "${options.project}" already has a ${options.buildTarget} target. Pass --skipValidation to ignore this error.`);
}
}
function addBuildTarget(tree, options, isTsSolutionSetup) {
(0, target_defaults_utils_1.addBuildTargetDefaults)(tree, '@nx/esbuild:esbuild', options.buildTarget);
const project = (0, devkit_1.readProjectConfiguration)(tree, options.project);
const prevBuildOptions = project.targets?.[options.buildTarget]?.options;
const tsConfig = prevBuildOptions?.tsConfig ?? getTsConfigFile(tree, options);
let outputPath = prevBuildOptions?.outputPath;
if (!outputPath) {
outputPath = isTsSolutionSetup
? (0, devkit_1.joinPathFragments)(project.root, 'dist')
: (0, devkit_1.joinPathFragments)('dist', project.root === '.' ? options.project : project.root);
}
const buildOptions = {
main: prevBuildOptions?.main ?? getMainFile(tree, options),
outputPath,
outputFileName: 'main.js',
tsConfig,
platform: options.platform,
format: options.format,
};
if (isTsSolutionSetup) {
buildOptions.declarationRootDir = (0, ts_solution_setup_1.getProjectSourceRoot)(project, tree);
}
else {
buildOptions.assets = [];
if (tree.exists((0, devkit_1.joinPathFragments)(project.root, 'README.md'))) {
buildOptions.assets.push({
glob: `${project.root}/README.md`,
input: '.',
output: '.',
});
}
}
if (options.platform === 'browser') {
buildOptions.outputHashing = 'all';
buildOptions.minify = true;
}
(0, devkit_1.updateProjectConfiguration)(tree, options.project, {
...project,
targets: {
...project.targets,
[options.buildTarget]: {
executor: '@nx/esbuild:esbuild',
outputs: ['{options.outputPath}'],
defaultConfiguration: 'production',
options: buildOptions,
configurations: {
development: {
minify: false,
},
production: {
minify: true,
},
},
},
},
});
}
function updatePackageJson(tree, options, isTsSolutionSetup) {
const project = (0, devkit_1.readProjectConfiguration)(tree, options.project);
const packageJsonPath = (0, posix_1.join)(project.root, 'package.json');
let packageJson;
if (tree.exists(packageJsonPath)) {
if (!isTsSolutionSetup) {
return;
}
packageJson = (0, devkit_1.readJson)(tree, packageJsonPath);
}
else {
packageJson = {
name: (0, get_import_path_1.getImportPath)(tree, options.project),
version: '0.0.1',
};
}
if (isTsSolutionSetup) {
const nxJson = (0, devkit_1.readNxJson)(tree);
const projectTarget = project.targets[options.buildTarget];
const mergedTarget = (0, devkit_internals_1.mergeTargetConfigurations)(projectTarget, (projectTarget.executor
? nxJson.targetDefaults?.[projectTarget.executor]
: undefined) ?? nxJson.targetDefaults?.[options.buildTarget]);
const { declarationRootDir = '.', main, outputPath, outputFileName,
// the executor option defaults to [esm]
format = ['esm'], esbuildOptions, } = mergedTarget.options;
// the file must exist in the TS solution setup
const tsconfigBase = (0, devkit_1.readJson)(tree, 'tsconfig.base.json');
// can't use the declarationRootDir as rootDir because it only affects the typings,
// not the runtime entry point
packageJson = (0, js_1.getUpdatedPackageJsonContent)(packageJson, {
main,
outputPath,
projectRoot: project.root,
generateExportsField: true,
packageJsonPath,
format,
outputFileName,
outputFileExtensionForCjs: (0, build_esbuild_options_1.getOutExtension)('cjs', {
// there's very little chance that the user would have defined a custom esbuild config
// since that's an Nx specific file that we're not generating here and we're setting up
// the build for esbuild now
userDefinedBuildOptions: esbuildOptions,
}),
outputFileExtensionForEsm: (0, build_esbuild_options_1.getOutExtension)('esm', {
userDefinedBuildOptions: esbuildOptions,
}),
developmentConditionName: (0, ts_solution_setup_1.getDefinedCustomConditionName)(tree),
});
if (declarationRootDir !== (0, posix_1.dirname)(main)) {
// the declaration file entry point will be output to a location
// different than the runtime entry point, adjust accodingly
const outputDir = (0, js_1.getOutputDir)({
main,
outputPath,
projectRoot: project.root,
packageJsonPath,
rootDir: declarationRootDir,
});
const mainFile = (0, posix_1.basename)(options.main).replace(/\.[tj]s$/, '');
const typingsFile = `${outputDir}${mainFile}.d.ts`;
packageJson.types = typingsFile;
packageJson.exports['.'].types = typingsFile;
}
}
(0, devkit_1.writeJson)(tree, packageJsonPath, packageJson);
}
function getMainFile(tree, options) {
const project = (0, devkit_1.readProjectConfiguration)(tree, options.project);
const candidates = [
(0, devkit_1.joinPathFragments)(project.root, 'src/main.ts'),
(0, devkit_1.joinPathFragments)(project.root, 'src/index.ts'),
];
for (const file of candidates) {
if (tree.exists(file))
return file;
}
return options.main;
}
function getTsConfigFile(tree, options) {
const project = (0, devkit_1.readProjectConfiguration)(tree, options.project);
const candidates = [
(0, devkit_1.joinPathFragments)(project.root, 'tsconfig.lib.json'),
(0, devkit_1.joinPathFragments)(project.root, 'tsconfig.app.json'),
];
for (const file of candidates) {
if (tree.exists(file))
return file;
}
return options.tsConfig;
}
exports.default = configurationGenerator;