UNPKG

@hqjs/babel-plugin-transform-name-imports

Version:

Transform name imports for web browser

113 lines (106 loc) 4.55 kB
// NOTE: complete mapping https://github.com/webpack/node-libs-browser // TODO: some names remain the same, but require library to be installed e.g. assert, buffer, events // TODO: serve this modules from hq instead of project root const BUILT_IN = { console: 'console-browserify', constants: 'constants-browserify', crypto: 'crypto-browserify', domain: 'domain-browser', http: 'stream-http', https: 'https-browserify', os: 'os-browserify', path: 'path-browserify', querystring: 'querystring-es3', stream: 'stream-browserify', sys: 'util', timers: 'timers-browserify', tty: 'tty-browserify', vm: 'vm-browserify', zlib: 'browserify-zlib', }; const NAME_PATTERN_MODULE = /((@[\w-.]+\/)?[\w-.]+)(.*)/; const resolveModulePath = (resolve, versions, browser, empty, value) => { const [, module, , rest] = NAME_PATTERN_MODULE.exec(value); if (typeof browser[value] === 'string') { return browser[value]; } else if (browser[value] === false) { return empty; } else if (typeof browser[module] === 'string') { return browser[module]; } else if (browser[module] === false) { return empty; } const name = rest === '' ? resolve[module] || versions[module] || BUILT_IN[module] || module : // version is present rest.startsWith('@') ? BUILT_IN[module] || module : versions[module] || BUILT_IN[module] || module; return `/node_modules/${name}${rest}`; }; const notNameImport = modName => (/^\.{0,2}\//).test(modName) || (/^https?:\/\//).test(modName) || (/^@\//).test(modName); const notRequire = (t, nodePath) => { const [requireArg, ...rest] = nodePath.node.arguments; return nodePath.node.callee.name !== 'require' || rest.length !== 0 || !t.isStringLiteral(requireArg) || nodePath.scope.hasBinding('require'); }; const notImport = (t, nodePath) => { const [requireArg, ...rest] = nodePath.node.arguments; return nodePath.node.callee.type !== 'Import' || rest.length !== 0 || !t.isStringLiteral(requireArg) || nodePath.scope.hasBinding('import'); }; module.exports = function ({ types: t }) { return { visitor: { CallExpression(nodePath, state) { const resolve = (state.opts && state.opts.resolve) || {}; const versions = (state.opts && state.opts.versions) || {}; const browser = (state.opts && state.opts.browser) || {}; const empty = (state.opts && state.opts.empty) || '/hq-empty-module.js'; const { node } = nodePath; if (notRequire(t, nodePath) && notImport(t, nodePath)) return; const [requireArg] = node.arguments; const { value: modName } = requireArg; if (notNameImport(modName)) return; requireArg.value = resolveModulePath(resolve, versions, browser, empty, modName); }, ExportNamedDeclaration(nodePath, state) { const resolve = (state.opts && state.opts.resolve) || {}; const versions = (state.opts && state.opts.versions) || {}; const browser = (state.opts && state.opts.browser) || {}; const empty = (state.opts && state.opts.empty) || '/hq-empty-module.js'; const { source } = nodePath.node; if (source === null) return; const { value: modName } = source; if (notNameImport(modName)) return; nodePath.node.source.value = resolveModulePath(resolve, versions, browser, empty, modName); }, ExportAllDeclaration(nodePath, state) { const resolve = (state.opts && state.opts.resolve) || {}; const versions = (state.opts && state.opts.versions) || {}; const browser = (state.opts && state.opts.browser) || {}; const empty = (state.opts && state.opts.empty) || '/hq-empty-module.js'; const { source } = nodePath.node; if (source === null) return; const { value: modName } = source; if (notNameImport(modName)) return; nodePath.node.source.value = resolveModulePath(resolve, versions, browser, empty, modName); }, ImportDeclaration(nodePath, state) { const resolve = (state.opts && state.opts.resolve) || {}; const versions = (state.opts && state.opts.versions) || {}; const browser = (state.opts && state.opts.browser) || {}; const empty = (state.opts && state.opts.empty) || '/hq-empty-module.js'; const { value: modName } = nodePath.node.source; if (notNameImport(modName)) return; nodePath.node.source.value = resolveModulePath(resolve, versions, browser, empty, modName); }, }, }; };