-
Notifications
You must be signed in to change notification settings - Fork 194
-
Notifications
You must be signed in to change notification settings - Fork 194
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
How to resolve and inline dynamic imports? #732
Comments
Pretty inlining is not trivial mostly because of dependencies of the thing you want to import and name clashes when you copy over text. If you're sure that you can statically resolve some imports, I suggest doing a transformation where you change |
Thank you. Is there a way to get the text behind the import inside of ts-morph? I'm asking because just adding it is in my case not enough. Before adding it I wanted to analyse the declaration behind the import. So I'm only analyzing declaration files. Any way to resolve it? Thanks for the help! :) |
Hey, @meandmax! I guess I'm 2 years late to this party, but I was trying to solve the same issue today and figured something out. If you are still in need of this, here it goes. This is the file I was testing on: async function dynaImport(): void {
const { SuppliersService } = await import('#services/ServiceSuppliers');
const test = new SuppliersService()
const somedef, {
attrs: IAttrs,
IFormattedAttrs,
} = await import('#data/Typings/attrs/attrs');
const something = await import('#services/ServiceSuppliers');
} Check this before. /**
* Counts identifiers by text value
* of a given sourceFile or a block, if provided
*/
export function countIndentifierByText(
text: string,
sourceFile: SourceFile,
block?: Node,
): number {
return (block ?? sourceFile).getDescendantsOfKind(SyntaxKind.Identifier)
.reduce((acc, idf) => {
if (idf.getText().replace(ESCAPE_STRING, '') === text.replace(ESCAPE_STRING, '')) {
return acc + 1;
}
return acc;
}, 0);
}
/**
* Checks is a sourceFile is an external library
* @param sourceFile
*/
function isImportALib(
sourceFile: SourceFile,
): boolean {
return sourceFile.getFilePath().includes('node_modules')
|| sourceFile.isInNodeModules()
|| sourceFile.isFromExternalLibrary();
}
/**
* Gets the source file's dynamic imports.
* @example
* const something = await import('some/where')
*
*/
export function getDynamicImports(
sourceFile: SourceFile,
): Omit<IImports, 'id'>[] {
return sourceFile
.getDescendantsOfKind(SyntaxKind.VariableStatement)
.filter((varStmt) => varStmt.getDescendantsOfKind(SyntaxKind.ImportKeyword).length)
.map((dinamicImport) => {
const parentBlock = dinamicImport
.getParentWhile((node) => node.getKind() === SyntaxKind.Block);
const defaultImport = dinamicImport
.getDescendantsOfKind(SyntaxKind.VariableDeclaration)
.filter((varDecl) => !varDecl.getDescendantsOfKind(SyntaxKind.ObjectBindingPattern).length)
.map((defaultImprt) => defaultImprt.getFirstChildByKind(SyntaxKind.Identifier)?.getText())[0];
const namedImports = dinamicImport.getDescendantsOfKind(SyntaxKind.BindingElement)
.map((destruct) => destruct.getDescendantsOfKind(SyntaxKind.Identifier))
.map((idf) => {
if (idf.length === 1) {
return {
name: idf[0].getText(),
isUsed: countIndentifierByText(idf[0].getText(), sourceFile, parentBlock) > 1,
};
}
return {
name: idf[0].getText(),
alias: idf[1].getText(),
isUsed: countIndentifierByText(idf[1].getText(), sourceFile, parentBlock) > 1,
};
});
const specifier = dinamicImport
.getDescendantsOfKind(SyntaxKind.SyntaxList)
.map((synList) => synList.getChildrenOfKind(SyntaxKind.StringLiteral))
.flat()[0];
const importSourceFile = specifier
? (
specifier
.getSymbol()?.getDeclarations()[0].getSourceFile()
)
: undefined;
const isLib = importSourceFile
? isImportALib(importSourceFile)
: undefined;
const isDefaultUsed = defaultImport
? countIndentifierByText(defaultImport, sourceFile, parentBlock) > 1
: undefined;
return {
defaultImport,
namedImports,
specifier: specifier?.getText(),
isTypeOnly: false,
isLib,
isUsed: isDefaultUsed,
resolvedPath: importSourceFile ? importSourceFile.getFilePath() : undefined,
};
});
} This whole ugly thing outputs this: [
{
namedImports: [
{
name: 'SuppliersService',
isUsed: true,
},
],
specifier: "'#services/ServiceSuppliers'",
isTypeOnly: false,
isLib: false,
resolvedPath: 'E:/Documents/CODE/WebDev/Lullo/backend/src/Services/Services/ServiceSuppliers.ts',
},
{
defaultImport: 'somedef',
namedImports: [
{
name: 'attrs',
alias: 'IAttrs',
isUsed: false,
},
{
name: 'IFormattedAttrs',
isUsed: false,
},
],
specifier: "'#data/Typings/attrs/attrs'",
isTypeOnly: false,
isLib: false,
isUsed: false,
resolvedPath: 'E:/Documents/CODE/WebDev/Lullo/backend/src/Data/Typings/attrs/attrs.ts',
},
{
defaultImport: 'something',
namedImports: [],
specifier: "'#services/ServiceSuppliers'",
isTypeOnly: false,
isLib: false,
isUsed: false,
resolvedPath: 'E:/Documents/CODE/WebDev/Lullo/backend/src/Services/Services/ServiceSuppliers.ts',
},
] Hope this helps someone in the future. |
I'm guessing that if you want know if it works in |
Am I able to resolve
import("myComponent")
and inline it with ts-morph?The text was updated successfully, but these errors were encountered: