Ts-morph: Browser/webpack support?

Created on 13 Dec 2017  路  13Comments  路  Source: dsherret/ts-morph

I assume this is being used in https://dsherret.github.io/ts-ast-viewer

I'm trying to make something similar-ish, but the fs dependency required by ast.addSourceFileFromText() means it's not so straightforward to implement in a browser. I've tried using browserfs to override it but am now getting different errors -
_os.platform is not a function

Am I missing an obvious solution here? Thanks

enhancement

All 13 comments

I'm actually only using the typescript compiler there. I've been meaning to open source that. (Edit: source code is available now https://github.com/dsherret/ts-ast-viewer)

I see os.platform only being used in the tests folder which are ignored when distributing on npm. There's probably some dependency this library has on something that does an os.platform check.

This hasn't been explicitly supported yet, but overall it wouldn't be too difficult to implement. Right now internally it would just need to use the VirtualFileSystemHost for the file system (that would probably need to be improved a bit) and then change the methods in FileUtils.ts to remove the dependency on "path". There is also one place in SourceFile.ts that I added recently that is incorrecting importing "path" instead of using FileUtils.ts.

Perhaps:

const ast = new Ast({
    useVirtualFileSystem: true
});
const fileSystem = ast.getFileSystem(); // only really useful when using a virtual file system

Thanks for the reply @dsherret. I also ended up using the TypeScript compiler directly, but I'll probably investigate using ts-simple-ast soon, starting with the approach you mentioned.

FYI, I opened #177 to implement this.

BTW, incase anyone comes across this post, before seeing @dsherret's suggestion above, I ended up using a virtual filesystem compiler host after reading this great blog post http://blog.scottlogic.com/2015/01/20/typescript-compiler-api.html

slightly modified the code so it works with typescript 2.6 -
https://gist.github.com/johnrees/4d29357768dd5e0fd98af56343d9819c

then called it with something like (untested)

  const host = new PatternCompilerHost();
  host.addFile("foo.ts", "function add(a:number,b:number) { return a+b }")
  const program = ts.createProgram(["foo.ts"], host.getCompilationSettings(), host);
  const checker = program.getTypeChecker();

  for (const sourceFile of program.getSourceFiles()) {
    ts.forEachChild(sourceFile, console.log);
  }

@johnrees fyi, the virtual file host for this library is available in v5.0. It works as described above.

There's still a dependency on nodejs' "path" though... maybe there's a way to make that work in the browser? If not, I will open an issue for removing the dependency on path.

We are going to try running ts-morph in the browser soon for our documentation tool. Glad to see it should mostly be possible? Will report back an issues. I think polyfilling path lib should be possible...

@jasonkuhrt I recently created a BrowserRuntime implementation (https://github.com/dsherret/ts-morph/blob/latest/packages/common/src/runtimes/BrowserRuntime.ts)

Just ensure it's using @ts-morph/common 0.9.1 behind the scenes and I believe it should work.

@dsherret - I'm still confused here, is there more documentation about how to use ts-morph in the browser? I'm trying this small script to parse an interface passed in as a string:

import { Project } from "ts-morph";

export const parseTypeScript = (typeScriptCode: string) => {
  const project = new Project();
  const sourceFile = project.createSourceFile("store/types.ts", typeScriptCode);

  // log errors (if any) here
  console.log(sourceFile.getPreEmitDiagnostics());
  const stateInterface = sourceFile.getInterface("MyState")!;

  // returns the properties
  console.log(stateInterface.getProperties()); 
};

and I'm getting a Uncaught Error: Not supported for the browser. in the browser console. Any guidance would be great!

@princefishthrower error message will be improved in the next version. Try const project = new Project({ useInMemoryFileSystem: true });

I think maybe the default of useInMemoryFileSystem should be true on browsers.

@dsherret - excellent, that did the trick!

I would definitely love to see a small section on the documentation on browser versus node based runtimes. :)

I have the latest [email protected] and @ts-morph/[email protected] but getting this on Next.js build:

image

@jasonkuhrt is there a way to get it to ignore that? I think the same thing would happen if importing the typescript compiler API directly. The TypeScript compiler code requires "perf_hooks" without specifying that as a dependency.

https://github.com/microsoft/TypeScript/issues/39436#issuecomment-739546225

@dsherret I am not sure but wouldn't be surprised if the basic issue here is the seemingly very much lacking tree-shaking ability of Nextjs via its use of webpack (we're on its bleeding edge Webpack 5 mode too).

I'll report back if we find a workaround.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

HoldYourWaffle picture HoldYourWaffle  路  4Comments

donaldpipowitch picture donaldpipowitch  路  5Comments

GrandSchtroumpf picture GrandSchtroumpf  路  3Comments

mi5ha picture mi5ha  路  3Comments

gt3 picture gt3  路  4Comments