stackgraph icon indicating copy to clipboard operation
stackgraph copied to clipboard

utility function to resolve `React.lazy` imports

Open scarf005 opened this issue 1 year ago • 0 comments

Example implementation

const resolveDynamicImportPath = (path: string) =>
  resolve(import.meta.dirname!) + path.replace('@src', '/src') + '.tsx'

const projectCache = new Project({
  useInMemoryFileSystem: true,
})

export const getRouteMappings =
  (resolveDynamicImport: (path: string) => string) =>
  (sourceFile: SourceFile): Record<string, string> => {
    const nodes = query(
      sourceFile.getText(),
      'Identifier[name=routes] ~ ObjectLiteralExpression > PropertyAssignment'
    ).flatMap((x) => {
      const container = query(x, 'Identifier[name=component] ~ Identifier')[0]
      if (container === undefined) return []

      const topDecl = sourceFile.getVariableDeclarationOrThrow(container?.getText())

      // HACK: assumes all components are of format React.lazy(() => import('<path>/componentName'))
      const path = topDecl.getFirstDescendantByKindOrThrow(SyntaxKind.StringLiteral)
      const resolvedPath = resolveDynamicImport(path.getLiteralText())
      const resolvedText = Deno.readTextFileSync(resolvedPath)

      const srcfile = projectCache.createSourceFile(resolvedPath, resolvedText)
      // https://ts-morph.com/details/exports#getting-exported-declarations
      const uri = encodeVSCodeURI(srcfile.getExportedDeclarations().get('default')![0])
      projectCache.removeSourceFile(srcfile)

      const name = query(x, 'PropertyAccessExpression Identifier[name=Route] ~ Identifier')[0]?.getText()

      return [[name, uri]] as const
    })

    return Object.fromEntries(nodes)
  }

scarf005 avatar Feb 14 '24 08:02 scarf005