UNPKG

@nx/esbuild

Version:

The Nx Plugin for esbuild contains executors and generators that support building applications using esbuild

182 lines (181 loc) • 7.89 kB
"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;