Skip to content

Instantly share code, notes, and snippets.

@developit
Created June 18, 2020 03:00
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save developit/4ba748d7d0196b780076b29e6f7a65c8 to your computer and use it in GitHub Desktop.
Save developit/4ba748d7d0196b780076b29e6f7a65c8 to your computer and use it in GitHub Desktop.

resolve-export-map

import { resolveExportMap } from 'resolve-export-map';

const demoMeta = {
  exports: {
    '.': './index.mjs',
    './foo': {
      import: './dist/foo.mjs',
      require: './dist/foo.cjs'
    },
    './bar': {
      browser: './bar/index.umd.js' // only used if "browser" env key is passed
    },
    './bar/': './bar/' // enable disk resolution within this dir
  }
};


resolveExportMap(demoMeta, '.', []) // './index.mjs'

resolveExportMap(demoMeta, './foo', []) // false  (no disk lookup allowed)
resolveExportMap(demoMeta, './foo', ['import']) // './dist/foo.mjs'
resolveExportMap(demoMeta, './foo', ['require', 'default']) // './dist/foo.mjs'

resolveExportMap(demoMeta, './bar', ['browser']) // './bar/index.umd.js'
resolveExportMap(demoMeta, './bar/test.js', []) // true  (disk lookup allowed)
/** Get the best resolution for an entry from an Export Map
* @param {Object} exp `package.exports`
* @param {string} entry `./foo` or `.`
* @param {string[]} [envKeys=ENV_KEYS] package environment keys
* @returns {string | boolean} a resolved path, or a boolean indicating if the given entry is exposed
*/
export function resolveExportMap(exp, entry, envKeys) {
if (typeof exp === 'string') {
// {"exports":"./foo.js"}
// {"exports":{"./foo":"./foo.js"}}
return exp;
}
let isFileListing;
let isDirectoryExposed = false;
for (let i in exp) {
if (isFileListing === undefined) isFileListing = i[0] === '.';
if (isFileListing) {
// {"exports":{".":"./index.js"}}
if (i === entry) {
return resolveExportMap(exp[i], entry, envKeys);
}
if (!isDirectoryExposed && i.endsWith('/') && entry.startsWith(i)) {
isDirectoryExposed = true;
}
} else if (envKeys.includes(i)) {
// {"exports":{"import":"./foo.js"}}
return resolveExportMap(exp[i], entry, envKeys);
}
}
return isDirectoryExposed;
}
@danielweck
Copy link

Thanks @developit :)
Your code snippet doesn't quite work for me (failed resolutions), but Lukeed's tiny NPM package has served me well: https://github.com/lukeed/resolve.exports

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment