import {
addDependenciesToPackageJson,
formatFiles,
ProjectConfiguration,
readJson,
readProjectConfiguration,
Tree,
updateProjectConfiguration
} from '@nx/devkit';
import { WebComponentConfigGeneratorSchema } from './schema';
import {
addBundleTarget,
updateBuildTarget,
updateDevelopTarget,
updateGenerateTarget,
updateServeTarget
} from './files/update-targets/update-targets';
const DEFAULT_CONFIGURATION_NAME = 'webcomponent';
export interface WebComponentTargetNames {
developTarget: string;
developConfiguration: string;
buildTarget: string;
buildConfiguration: string;
serveTarget: string;
serveConfiguration: string;
generateTarget: string;
generateConfiguration: string;
bundleTarget: string;
}
export default async function addWebComponentConfig(
tree: Tree,
options: WebComponentConfigGeneratorSchema
) {
const targetNames = getTargetNamesFromOptions(options);
const project = readProjectConfiguration(tree, options.project);
verifyTargetNames(project, targetNames);
const projectDistFolder = project.targets?.[targetNames.buildTarget]?.options?.outputPath;
if (!projectDistFolder) {
throw new Error(
`Cannot determine the output path of the target "${targetNames.buildTarget}". Please specify "options.outputPath" in "${targetNames.buildTarget}" and make sure to follow the recommendations about building a web component from the TALY documentation:
https://taly.frameworks.allianz.io/additional-documentation/app-generation/app-as-web-component.html
`
);
}
updateBuildTarget(project, targetNames, options?.deployUrl);
updateServeTarget(project, targetNames);
updateDevelopTarget(project, targetNames);
updateGenerateTarget(project, targetNames);
addBundleTarget(project, projectDistFolder, targetNames);
updateProjectConfiguration(tree, options.project, project);
await formatFiles(tree);
const parsedPackageJson = readJson(tree, 'package.json');
const version = parsedPackageJson?.dependencies?.['@angular/compiler'];
// Nx sets npm_config_legacy_peer_deps = true by default inside the `installPackagesTask` (https://github.com/nrwl/nx/blob/5ded713c3c487bd28874e75b1623ece07a79d91d/packages/nx/src/utils/package-manager.ts#L130)
// We have to explicitly set it to prevent the default behavior
process.env['npm_config_legacy_peer_deps'] ??= 'false';
return addDependenciesToPackageJson(tree, { '@angular/elements': version }, {});
}
function getTargetNamesFromOptions(
options: WebComponentConfigGeneratorSchema
): WebComponentTargetNames {
const [developTarget, developConfiguration] = parseTargetName(options.developTarget, 'develop');
const [buildTarget, buildConfiguration] = parseTargetName(
options.buildTarget,
'build-generated-app'
);
const [serveTarget, serveConfiguration] = parseTargetName(
options.serveTarget,
'serve-generated-app'
);
const [generateTarget, generateConfiguration] = parseTargetName(
options.generateTarget,
'generate-only'
);
const bundleTarget = options?.bundleTarget || 'webcomponent-bundle';
return {
developTarget,
developConfiguration,
buildTarget,
buildConfiguration,
serveTarget,
serveConfiguration,
generateTarget,
generateConfiguration,
bundleTarget
};
}
function parseTargetName(target: string | undefined, defaultTarget: string): [string, string] {
if (!target) {
return [defaultTarget, DEFAULT_CONFIGURATION_NAME];
}
const [specifiedTarget, specifiedConfiguration] = target.split(':');
return [specifiedTarget, specifiedConfiguration || DEFAULT_CONFIGURATION_NAME];
}
function verifyTargetNames(project: ProjectConfiguration, targets: WebComponentTargetNames) {
const projectTargets = project?.targets;
if (projectTargets === undefined) {
throw new Error(
`⚠️ The project "${project.name}" does not have any targets defined. Please consider adding a "serve-generated-app", "build-generated-app", "develop" and "generate-only" target.`
);
}
const specifiedTargetNames = [
targets.developTarget,
targets.buildTarget,
targets.serveTarget,
targets.generateTarget
];
const undefinedTargets = specifiedTargetNames.filter(
(targetName) => !(targetName in projectTargets)
);
if (undefinedTargets.length > 0) {
throw new Error(
`⚠️ The project "${
project.name
}" does not have the following targets defined: ${undefinedTargets.join(', ')}.`
);
}
}