chore(providence-analytics): allow deprecated export map notation
This commit is contained in:
parent
2028277cd1
commit
ba16e23b00
2 changed files with 76 additions and 19 deletions
|
|
@ -218,18 +218,17 @@ function normalizeLocalPathWithDotSlash(localPathWithoutDotSlash) {
|
|||
|
||||
/**
|
||||
* @param {{val:object|string;nodeResolveMode:string}} opts
|
||||
* @returns {string}
|
||||
* @returns {string|null}
|
||||
*/
|
||||
function getStringOrObjectValOfExportMapEntry({ val, nodeResolveMode, packageRootPath }) {
|
||||
if (typeof val !== 'object') {
|
||||
return val;
|
||||
function getStringOrObjectValOfExportMapEntry({ valObjOrStr, nodeResolveMode }) {
|
||||
if (typeof valObjOrStr !== 'object') {
|
||||
return valObjOrStr;
|
||||
}
|
||||
if (!val[nodeResolveMode]) {
|
||||
throw new Error(
|
||||
`[getExportMapExports]: nodeResolveMode "${nodeResolveMode}" not found in package.json of package ${packageRootPath}`,
|
||||
);
|
||||
if (!valObjOrStr[nodeResolveMode]) {
|
||||
// This is allowed: it makes sense to have an entrypoint on the root for typescript, not for others
|
||||
return null;
|
||||
}
|
||||
return val[nodeResolveMode];
|
||||
return valObjOrStr[nodeResolveMode];
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -355,7 +354,12 @@ class InputDataService {
|
|||
/** @type {ProjectInputDataWithMeta['entries'][]} */
|
||||
const newEntries = [];
|
||||
projectObj.entries.forEach(entry => {
|
||||
const code = fs.readFileSync(entry, 'utf8');
|
||||
let code;
|
||||
try {
|
||||
code = fs.readFileSync(entry, 'utf8');
|
||||
} catch (e) {
|
||||
LogService.error(`Could not find "${entry}"`);
|
||||
}
|
||||
const file = getFilePathRelativeFromRoot(
|
||||
toPosixPath(entry),
|
||||
toPosixPath(projectObj.project.path),
|
||||
|
|
@ -613,7 +617,7 @@ class InputDataService {
|
|||
}
|
||||
|
||||
/**
|
||||
* @param {object} exports
|
||||
* @param {{[key:string]: string|object}} exports
|
||||
* @param {object} opts
|
||||
* @param {'default'|'development'|string} [opts.nodeResolveMode='default']
|
||||
* @param {string} opts.packageRootPath
|
||||
|
|
@ -622,23 +626,36 @@ class InputDataService {
|
|||
static getPathsFromExportMap(exports, { nodeResolveMode = 'default', packageRootPath }) {
|
||||
const exportMapPaths = [];
|
||||
|
||||
for (const [key, val] of Object.entries(exports)) {
|
||||
if (!key.includes('*')) {
|
||||
for (const [key, valObjOrStr] of Object.entries(exports)) {
|
||||
let resolvedKey = key;
|
||||
let resolvedVal = getStringOrObjectValOfExportMapEntry({ valObjOrStr, nodeResolveMode });
|
||||
if (resolvedVal === null) {
|
||||
// eslint-disable-next-line no-continue
|
||||
continue;
|
||||
}
|
||||
|
||||
// Allow older specs like "./__element-definitions/" : "./__element-definitions/" to also work,
|
||||
// so we normalize them to the new spec
|
||||
if (resolvedVal.endsWith?.('/') && resolvedKey.endsWith('/')) {
|
||||
resolvedVal += '*';
|
||||
resolvedKey += '*';
|
||||
}
|
||||
|
||||
if (!resolvedKey.includes('*')) {
|
||||
exportMapPaths.push({
|
||||
internal: getStringOrObjectValOfExportMapEntry({ val, nodeResolveMode, packageRootPath }),
|
||||
exposed: key,
|
||||
internal: resolvedVal,
|
||||
exposed: resolvedKey,
|
||||
});
|
||||
// eslint-disable-next-line no-continue
|
||||
continue;
|
||||
}
|
||||
|
||||
const valueToUseForGlob = stripDotSlashFromLocalPath(
|
||||
getStringOrObjectValOfExportMapEntry({ val, nodeResolveMode, packageRootPath }),
|
||||
);
|
||||
const valueToUseForGlob = stripDotSlashFromLocalPath(resolvedVal);
|
||||
|
||||
// Generate all possible entries via glob, first strip './'
|
||||
const internalExportMapPathsForKeyRaw = glob.sync(valueToUseForGlob, {
|
||||
cwd: packageRootPath,
|
||||
nodir: true,
|
||||
});
|
||||
|
||||
const exposedExportMapPathsForKeyRaw = internalExportMapPathsForKeyRaw.map(pathInside => {
|
||||
|
|
@ -648,7 +665,7 @@ class InputDataService {
|
|||
const [, variablePart] = pathInside.match(
|
||||
new RegExp(valueToUseForGlob.replace('*', '(.*)')),
|
||||
);
|
||||
return key.replace('*', variablePart);
|
||||
return resolvedKey.replace('*', variablePart);
|
||||
});
|
||||
const internalExportMapPathsForKey = internalExportMapPathsForKeyRaw.map(filePath =>
|
||||
normalizeLocalPathWithDotSlash(filePath),
|
||||
|
|
|
|||
|
|
@ -655,6 +655,46 @@ build/
|
|||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Deprecated root mappings ("/" instead of "/*")', () => {
|
||||
it('works for values defined as strings', async () => {
|
||||
const fakeFs = {
|
||||
'/my/proj/internal-folder/file-a.js': 'export const a = 1;',
|
||||
'/my/proj/internal-folder/file-b.js': 'export const b = 2;',
|
||||
};
|
||||
mock(fakeFs);
|
||||
const exports = {
|
||||
// An old spec that
|
||||
'./exposed-folder/': './internal-folder/',
|
||||
};
|
||||
const exportMapPaths = await InputDataService.getPathsFromExportMap(exports, {
|
||||
packageRootPath: '/my/proj',
|
||||
});
|
||||
expect(exportMapPaths).to.eql([
|
||||
{ internal: './internal-folder/file-a.js', exposed: './exposed-folder/file-a.js' },
|
||||
{ internal: './internal-folder/file-b.js', exposed: './exposed-folder/file-b.js' },
|
||||
]);
|
||||
});
|
||||
|
||||
it('works for values defined as objects', async () => {
|
||||
const fakeFs = {
|
||||
'/my/proj/internal-folder/file-a.js': 'export const a = 1;',
|
||||
'/my/proj/internal-folder/file-b.js': 'export const b = 2;',
|
||||
};
|
||||
mock(fakeFs);
|
||||
const exports = {
|
||||
// An old spec that
|
||||
'./exposed-folder/': { default: './internal-folder/' },
|
||||
};
|
||||
const exportMapPaths = await InputDataService.getPathsFromExportMap(exports, {
|
||||
packageRootPath: '/my/proj',
|
||||
});
|
||||
expect(exportMapPaths).to.eql([
|
||||
{ internal: './internal-folder/file-a.js', exposed: './exposed-folder/file-a.js' },
|
||||
{ internal: './internal-folder/file-b.js', exposed: './exposed-folder/file-b.js' },
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in a new issue