nx-esbuild-decorators
Version:
The Nx Plugin for esbuild contains executors and generators that support building applications using esbuild and also supports decorators
134 lines (118 loc) • 3.75 kB
text/typescript
import type { Tree } from '@nx/devkit';
import {
formatFiles,
joinPathFragments,
readProjectConfiguration,
updateProjectConfiguration,
writeJson,
} from '@nx/devkit';
import { getImportPath } from '@nx/js/src/utils/get-import-path';
import { esbuildInitGenerator } from '../init/init';
import { EsBuildExecutorOptions } from '../../executors/esbuild/schema';
import { EsBuildProjectSchema } from './schema';
export async function configurationGenerator(
tree: Tree,
options: EsBuildProjectSchema
) {
const task = await esbuildInitGenerator(tree, {
...options,
skipFormat: true,
});
options.buildTarget ??= 'build';
checkForTargetConflicts(tree, options);
addBuildTarget(tree, options);
await formatFiles(tree);
return task;
}
function checkForTargetConflicts(tree: Tree, options: EsBuildProjectSchema) {
if (options.skipValidation) return;
const project = 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: Tree, options: EsBuildProjectSchema) {
const project = readProjectConfiguration(tree, options.project);
const packageJsonPath = joinPathFragments(project.root, 'package.json');
if (!tree.exists(packageJsonPath)) {
const importPath =
options.importPath || getImportPath(tree, options.project);
writeJson(tree, packageJsonPath, {
name: importPath,
version: '0.0.1',
});
}
const prevBuildOptions = project.targets?.[options.buildTarget]?.options;
const tsConfig = prevBuildOptions?.tsConfig ?? getTsConfigFile(tree, options);
const buildOptions: EsBuildExecutorOptions = {
main: prevBuildOptions?.main ?? getMainFile(tree, options),
outputPath:
prevBuildOptions?.outputPath ??
joinPathFragments(
'dist',
project.root === '.' ? options.project : project.root
),
outputFileName: 'main.js',
tsConfig,
assets: [],
platform: options.platform,
};
if (options.platform === 'browser') {
buildOptions.outputHashing = 'all';
buildOptions.minify = true;
}
if (tree.exists(joinPathFragments(project.root, 'README.md'))) {
buildOptions.assets = [
{
glob: `${project.root}/README.md`,
input: '.',
output: '.',
},
];
}
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 getMainFile(tree: Tree, options: EsBuildProjectSchema) {
const project = readProjectConfiguration(tree, options.project);
const candidates = [
joinPathFragments(project.root, 'src/main.ts'),
joinPathFragments(project.root, 'src/index.ts'),
];
for (const file of candidates) {
if (tree.exists(file)) return file;
}
return options.main;
}
function getTsConfigFile(tree: Tree, options: EsBuildProjectSchema) {
const project = readProjectConfiguration(tree, options.project);
const candidates = [
joinPathFragments(project.root, 'tsconfig.lib.json'),
joinPathFragments(project.root, 'tsconfig.app.json'),
];
for (const file of candidates) {
if (tree.exists(file)) return file;
}
return options.tsConfig;
}
export default configurationGenerator;