fix(bazel): ng_package rule should update "package.json" of ts_library targets (#36944)

In the past we added support for `ts_library` to `ng_package`. For those
targets we never can determine the "index" file. Unlike `ng_module`,
there is no provider data for flat module bundles, so the `ng_package`
rule assumes that the index file is simply called `index`.

This works as expected, but we also added logic in the past that doesn't
allow `ng_package` to add format properties (e.g. `main`, `module`) to a
`package.json` if a package json is handwritten for such a `ts_library` target.

This has been done that way because we assumed that such `package.json` files
might want to set format properties explicitly to different paths due to a
faulty "index" guess.

We want to change this behavior as most of the time a `package.json`
file already exists with just the module name. In those cases, the
packager should still set the format properties. We should only warn
and skip automatic insertion of the format properties if such a
`package.json` explicitly sets format properties.

PR Close #36944
This commit is contained in:
Paul Gschwendtner 2020-05-06 12:45:26 +02:00 committed by Alex Rickabaugh
parent d578ab8f3c
commit d5293d2aa3

View File

@ -102,6 +102,13 @@ function main(args: string[]): number {
const modulesManifest = JSON.parse(modulesManifestArg); const modulesManifest = JSON.parse(modulesManifestArg);
const dtsBundles: string[] = dtsBundleArg.split(',').filter(s => !!s); const dtsBundles: string[] = dtsBundleArg.split(',').filter(s => !!s);
/**
* List of known `package.json` fields which provide information about
* supported package formats and their associated entry paths.
*/
const knownFormatPackageJsonFields =
['main', 'fesm2015', 'esm2015', 'typings', 'module', 'es2015'];
if (readmeMd) { if (readmeMd) {
copyFile(readmeMd, out); copyFile(readmeMd, out);
} }
@ -324,11 +331,10 @@ function main(args: string[]): number {
const packageName = parsedPackage['name']; const packageName = parsedPackage['name'];
const moduleData = modulesManifest[packageName]; const moduleData = modulesManifest[packageName];
// We don't want to modify the "package.json" if we guessed the entry-point // If a package json file has been discovered that does not match any
// paths and there is a custom "package.json" for that package already. Module // module in the manifest, we report a warning as most likely the target
// data will be only undefined if the package name comes from a non-generated // is configured incorrectly (e.g. missing `module_name` attribute).
// "package.json". In that case we want to leave the file untouched as well. if (!moduleData) {
if (!moduleData || moduleData.guessedPaths && !isGeneratedPackageJson) {
// Ideally we should throw here, as we got an entry point that doesn't // Ideally we should throw here, as we got an entry point that doesn't
// have flat module metadata / bundle index, so it may have been an // have flat module metadata / bundle index, so it may have been an
// ng_module that's missing a module_name attribute. // ng_module that's missing a module_name attribute.
@ -342,6 +348,19 @@ function main(args: string[]): number {
return JSON.stringify(parsedPackage, null, 2); return JSON.stringify(parsedPackage, null, 2);
} }
// If we guessed the index paths for a module, and it contains an explicit `package.json`
// file that already sets format properties, we skip automatic insertion of format
// properties but report a warning in case properties have been set by accident.
if (moduleData.guessedPaths && !isGeneratedPackageJson &&
hasExplicitFormatProperties(parsedPackage)) {
console.error('WARNING: `package.json` explicitly sets format properties (like `main`).');
console.error(
' Skipping automatic insertion of format properties as explicit ' +
'format properties are set.');
console.error(' Ignore this warning if explicit properties are set intentionally.');
return JSON.stringify(parsedPackage, null, 2);
}
// Derive the paths to the files from the hard-coded names we gave them. // Derive the paths to the files from the hard-coded names we gave them.
// TODO(alexeagle): it would be better to transfer this information from the place // TODO(alexeagle): it would be better to transfer this information from the place
// where we created the filenames, via the modulesManifestArg // where we created the filenames, via the modulesManifestArg
@ -377,6 +396,12 @@ function main(args: string[]): number {
return [relativePath, dir, basename + '.js'].join('/'); return [relativePath, dir, basename + '.js'].join('/');
} }
/** Whether the package explicitly sets any of the format properties (like `main`). */
function hasExplicitFormatProperties(parsedPackage: {[key: string]: string}): boolean {
return Object.keys(parsedPackage)
.some(propertyName => knownFormatPackageJsonFields.includes(propertyName));
}
/** Creates metadata re-export file for a secondary entry-point. */ /** Creates metadata re-export file for a secondary entry-point. */
function createMetadataReexportFile( function createMetadataReexportFile(
entryPointName: string, metadataFile: string, packageName: string) { entryPointName: string, metadataFile: string, packageName: string) {