Created
November 23, 2021 19:27
-
-
Save Grohden/b351dc6f45971755eddcb3c30c20dbe8 to your computer and use it in GitHub Desktop.
Script that resolves all exports + paths from TS barrel files, meant to be used with babel-transform-imports
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const fs = require('fs'); | |
const path = require('path'); | |
const ts = require('typescript'); | |
/** | |
* Parses a barrel (index) file, extracts all it's export | |
* names and returns an object that maps | |
* a import name to the path + some meta infos. | |
* | |
* | |
* Note: this doesn't handle the following cases: | |
* ``` | |
* import {A, B} from './foo'; | |
* | |
* export {A,B} | |
* | |
* export * as Namespace from './foo'; | |
* ``` | |
* | |
* The case above is not supported. | |
*/ | |
const collectExports = (file) => { | |
const sourceFile = ts.createSourceFile( | |
file, | |
fs.readFileSync(file).toString(), | |
ts.ScriptTarget.ES2015, | |
true, | |
); | |
const exports = {}; | |
sourceFile.forEachChild((child) => { | |
if (ts.isExportDeclaration(child)) { | |
if (child.exportClause && child.moduleSpecifier) { | |
const importName = child.moduleSpecifier.text; | |
child.exportClause.forEachChild((node) => { | |
if (ts.isExportSpecifier(node)) { | |
exports[node.name.text] = { | |
importPath: importName, | |
isDefault: node.propertyName !== undefined, | |
}; | |
} | |
}); | |
} | |
} | |
}); | |
return exports; | |
}; | |
/** | |
* Given a result from the collectExports returns a | |
* import module string for the given member | |
*/ | |
const memberImportSolver = (libImportPath, mappings) => (member) => { | |
const mapping = mappings[member]; | |
if (!mapping) { | |
throw new Error(`Could not find mapping for ${member}`); | |
} | |
return path.join(libImportPath, mapping.importPath); | |
}; | |
/** | |
* Transforms the object from collectExports into a object | |
* that has a key as the import name and the value as the alias original name | |
*/ | |
const importAliases = (info) => { | |
return Object.keys(info).reduce((aliases, key) => { | |
const value = info[key]; | |
if (value.isDefault) { | |
aliases[key] = 'default'; | |
} else { | |
aliases[key] = key; | |
} | |
return aliases; | |
}, {}); | |
}; | |
module.exports = { | |
collectExports, | |
memberImportSolver, | |
importAliases, | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment