From 00344c25ebf5c4282c8451658817742a74081249 Mon Sep 17 00:00:00 2001 From: Manfred Steyer Date: Sat, 28 May 2022 01:06:34 +0200 Subject: [PATCH] feat(mf): respect APF v14 for discovering secondaries before, the folders of the shared packages have been searched for subfolders with a package.json. These subfolders were added as secondary entry points. Now, if the package.json contains an exports field, like defined by APF v14, this field is used to find out about secondary entry points. If this is not the case, the original logic described aboved is used as a fallback. --- libs/mf/src/utils/share-utils.ts | 83 ++++++++++++++++++++++++++------ 1 file changed, 68 insertions(+), 15 deletions(-) diff --git a/libs/mf/src/utils/share-utils.ts b/libs/mf/src/utils/share-utils.ts index 4943267a..ae5005b8 100644 --- a/libs/mf/src/utils/share-utils.ts +++ b/libs/mf/src/utils/share-utils.ts @@ -13,6 +13,11 @@ export const DEFAULT_SKIP_LIST = [ 'zone.js' ]; +export const DEFAULT_SECONARIES_SKIP_LIST = [ + '@angular/router/upgrade', + '@angular/common/upgrade' +]; + type VersionMap = Record; type IncludeSecondariesOptions = { skip: string | string[] } | boolean; type CustomSharedConfig = SharedConfig & { includeSecondaries?: IncludeSecondariesOptions }; @@ -80,7 +85,7 @@ function lookupVersion(key: string, versions: VersionMap): string { return versions[key]; } -function _findSecondaries(libPath: string, excludes: string[], acc: string[]): void { +function _findSecondaries(libPath: string, excludes: string[], shareObject: SharedConfig, acc: Record): void { const files = fs.readdirSync(libPath); @@ -94,19 +99,19 @@ function _findSecondaries(libPath: string, excludes: string[], acc: string[]): v if (excludes.includes(secondaryLibName)) { continue; } - acc.push(secondaryLibName); - _findSecondaries(s, excludes, acc); + acc[secondaryLibName] = {...shareObject}; + _findSecondaries(s, excludes, shareObject, acc); } } -function findSecondaries(libPath: string, excludes: string[]): string[] { - const acc = []; - _findSecondaries(libPath, excludes, acc); +function findSecondaries(libPath: string, excludes: string[], shareObject: SharedConfig): Record { + const acc = {} as Record; + _findSecondaries(libPath, excludes, shareObject, acc); return acc; } -function getSecondaries(includeSecondaries: IncludeSecondariesOptions, packagePath: string, key: string): string[] { - let exclude = []; +function getSecondaries(includeSecondaries: IncludeSecondariesOptions, packagePath: string, key: string, shareObject: SharedConfig): Record { + let exclude = [...DEFAULT_SECONARIES_SKIP_LIST]; if (typeof includeSecondaries === 'object' ) { if (Array.isArray(includeSecondaries.skip)) { @@ -119,14 +124,54 @@ function getSecondaries(includeSecondaries: IncludeSecondariesOptions, packagePa const libPath = path.join(path.dirname(packagePath), 'node_modules', key); - const secondaries = findSecondaries(libPath, exclude); + const configured = readConfiguredSecondaries(key, libPath, exclude, shareObject); + if (configured) { + return configured; + } + + // Fallback: Search folders + const secondaries = findSecondaries(libPath, exclude, shareObject); return secondaries; } -function addSecondaries(secondaries: string[], result: Config, shareObject: Config): void { - for (const s of secondaries) { - result[s] = shareObject; +function readConfiguredSecondaries(parent: string, libPath: string, exclude: string[], shareObject: SharedConfig): Record { + const libPackageJson = path.join(libPath, 'package.json'); + + if (!fs.existsSync(libPackageJson)) { + return null; } + + const packageJson = JSON.parse(fs.readFileSync(libPackageJson, 'utf-8')); + const exports = packageJson['exports'] as Record>; + + if (!exports) { + return null; + } + + const keys = Object.keys(exports) + .filter(key => key != '.' + && key != './package.json' + && !key.endsWith('*') + && exports[key]['default']); + + const result = {} as Record; + + for(const key of keys) { + const relPath = exports[key]['default']; + const secondaryName = path.join(parent, key).replace(/\\/g, '/'); + + if (exclude.includes(secondaryName)) { + continue; + } + + result[secondaryName] = { + ...shareObject, + import: path.join(libPath, relPath) + } + } + + return result; + } export function shareAll(config: CustomSharedConfig = {}, skip: string[] = DEFAULT_SKIP_LIST, packageJsonPath = ''): Config { @@ -174,7 +219,9 @@ export function share(shareObjects: Config, packageJsonPath = ''): Config { const shareObject = shareObjects[key]; if (shareObject.requiredVersion === 'auto' || (inferVersion && typeof shareObject.requiredVersion === 'undefined')) { - shareObject.requiredVersion = lookupVersion(key, versions); + const version = lookupVersion(key, versions); + shareObject.requiredVersion = version; + shareObject.version = version.replace(/^\D*/, ''); } if (typeof shareObject.includeSecondaries === 'undefined') { @@ -189,11 +236,17 @@ export function share(shareObjects: Config, packageJsonPath = ''): Config { result[key] = shareObject; if (includeSecondaries) { - const secondaries = getSecondaries(includeSecondaries, packagePath, key); - addSecondaries(secondaries, result, shareObject); + const secondaries = getSecondaries(includeSecondaries, packagePath, key, shareObject); + addSecondaries(secondaries, result); } } return result; } +function addSecondaries(secondaries: Record, result: {}) { + for (const key in secondaries) { + result[key] = secondaries[key]; + } +} +