fix(ivy): ngcc - infer entry-point typings from format paths (#30591)
Some packages do not actually provide a `typings` field in their package.json. But TypeScript naturally infers the typings file from the location of the JavaScript source file. This commit modifies ngcc to do a similar inference when finding entry-points to process. Fixes #28603 (FW-1299) PR Close #30591
This commit is contained in:
parent
7c4c676413
commit
869e3e8edc
@ -91,7 +91,8 @@ export function getEntryPointInfo(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// We must have a typings property
|
// We must have a typings property
|
||||||
const typings = entryPointPackageJson.typings || entryPointPackageJson.types;
|
const typings = entryPointPackageJson.typings || entryPointPackageJson.types ||
|
||||||
|
guessTypingsFromPackageJson(fs, entryPointPath, entryPointPackageJson);
|
||||||
if (!typings) {
|
if (!typings) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -191,3 +192,21 @@ function mergeConfigAndPackageJson(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function guessTypingsFromPackageJson(
|
||||||
|
fs: FileSystem, entryPointPath: AbsoluteFsPath,
|
||||||
|
entryPointPackageJson: EntryPointPackageJson): AbsoluteFsPath|null {
|
||||||
|
for (const prop of SUPPORTED_FORMAT_PROPERTIES) {
|
||||||
|
const field = entryPointPackageJson[prop];
|
||||||
|
if (typeof field !== 'string') {
|
||||||
|
// Some crazy packages have things like arrays in these fields!
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const relativeTypingsPath = field.replace(/\.js$/, '.d.ts');
|
||||||
|
const typingsPath = resolve(entryPointPath, relativeTypingsPath);
|
||||||
|
if (fs.exists(typingsPath)) {
|
||||||
|
return typingsPath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
@ -10,7 +10,7 @@ import {AbsoluteFsPath, FileSystem, absoluteFrom, getFileSystem} from '../../../
|
|||||||
import {runInEachFileSystem} from '../../../src/ngtsc/file_system/testing';
|
import {runInEachFileSystem} from '../../../src/ngtsc/file_system/testing';
|
||||||
import {loadTestFiles} from '../../../test/helpers';
|
import {loadTestFiles} from '../../../test/helpers';
|
||||||
import {NgccConfiguration} from '../../src/packages/configuration';
|
import {NgccConfiguration} from '../../src/packages/configuration';
|
||||||
import {getEntryPointInfo} from '../../src/packages/entry_point';
|
import {SUPPORTED_FORMAT_PROPERTIES, getEntryPointInfo} from '../../src/packages/entry_point';
|
||||||
import {MockLogger} from '../helpers/mock_logger';
|
import {MockLogger} from '../helpers/mock_logger';
|
||||||
|
|
||||||
runInEachFileSystem(() => {
|
runInEachFileSystem(() => {
|
||||||
@ -178,6 +178,43 @@ runInEachFileSystem(() => {
|
|||||||
expect(entryPoint).toBe(null);
|
expect(entryPoint).toBe(null);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
for (let prop of SUPPORTED_FORMAT_PROPERTIES) {
|
||||||
|
// Ignore the UMD format
|
||||||
|
if (prop === 'main') continue;
|
||||||
|
// Let's give 'module' a specific path, otherwise compute it based on the property.
|
||||||
|
const typingsPath = prop === 'module' ? 'index' : `${prop}/missing_typings`;
|
||||||
|
|
||||||
|
it(`should return an object if it can guess the typings path from the "${prop}" field`, () => {
|
||||||
|
loadTestFiles([
|
||||||
|
{
|
||||||
|
name: _('/project/node_modules/some_package/missing_typings/package.json'),
|
||||||
|
contents: createPackageJson('missing_typings', {excludes: ['typings']}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: _(
|
||||||
|
`/project/node_modules/some_package/missing_typings/${typingsPath}.metadata.json`),
|
||||||
|
contents: 'some meta data',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: _(`/project/node_modules/some_package/missing_typings/${typingsPath}.d.ts`),
|
||||||
|
contents: '// some typings file',
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
const config = new NgccConfiguration(fs, _('/project'));
|
||||||
|
const entryPoint = getEntryPointInfo(
|
||||||
|
fs, config, new MockLogger(), SOME_PACKAGE,
|
||||||
|
_('/project/node_modules/some_package/missing_typings'));
|
||||||
|
expect(entryPoint).toEqual({
|
||||||
|
name: 'some_package/missing_typings',
|
||||||
|
package: SOME_PACKAGE,
|
||||||
|
path: _('/project/node_modules/some_package/missing_typings'),
|
||||||
|
typings: _(`/project/node_modules/some_package/missing_typings/${typingsPath}.d.ts`),
|
||||||
|
packageJson: loadPackageJson(fs, '/project/node_modules/some_package/missing_typings'),
|
||||||
|
compiledByAngular: true,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
it('should return an object with `compiledByAngular` set to false if there is no metadata.json file next to the typing file',
|
it('should return an object with `compiledByAngular` set to false if there is no metadata.json file next to the typing file',
|
||||||
() => {
|
() => {
|
||||||
loadTestFiles([
|
loadTestFiles([
|
||||||
@ -311,9 +348,11 @@ runInEachFileSystem(() => {
|
|||||||
[typingsProp]: `./${packageName}.d.ts`,
|
[typingsProp]: `./${packageName}.d.ts`,
|
||||||
fesm2015: `./fesm2015/${packageName}.js`,
|
fesm2015: `./fesm2015/${packageName}.js`,
|
||||||
esm2015: `./esm2015/${packageName}.js`,
|
esm2015: `./esm2015/${packageName}.js`,
|
||||||
fesm5: `./fesm2015/${packageName}.js`,
|
es2015: `./es2015/${packageName}.js`,
|
||||||
esm5: `./esm2015/${packageName}.js`,
|
fesm5: `./fesm5/${packageName}.js`,
|
||||||
|
esm5: `./esm5/${packageName}.js`,
|
||||||
main: `./bundles/${packageName}.umd.js`,
|
main: `./bundles/${packageName}.umd.js`,
|
||||||
|
module: './index.js',
|
||||||
};
|
};
|
||||||
if (excludes) {
|
if (excludes) {
|
||||||
excludes.forEach(exclude => delete packageJson[exclude]);
|
excludes.forEach(exclude => delete packageJson[exclude]);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user