Skip to content
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

Any plan for a Go API? #152

Closed
bep opened this issue May 26, 2020 · 11 comments
Closed

Any plan for a Go API? #152

bep opened this issue May 26, 2020 · 11 comments

Comments

@bep
Copy link

bep commented May 26, 2020

I'm leading the Hugo project, and esbuild delivers something I have been wanting badly to integrate for a long, long time.

Unfortunately, for good reasons I'm sure, there does not seem to be a public Go API. The main function is easy to understand and seem to cover what we need, but all the API it calls lives in the internal package.

Any plans making (at least part of) this public? Note that I don't mind API-breakage in < 1 versions and would love to get to test this out.

gohugoio/hugo#7321

@earthboundkid
Copy link

IMO, a good compromise if the project wants to keep its APIs internal is to create an app.CLI(args []string) error public function that main can call. This lets other Go projects embed esbuild without having to install a binary somewhere or committing to any public interface beyond the CLI. I use this pattern quite often, e.g. here.

@bep
Copy link
Author

bep commented May 26, 2020

app.CLI(args []string) error

Not to get ahead of myself here, but for this to be practical/usable for Hugo, we would need access to the filesystem/resolver API, i.e. something more powerful than the above.

@earthboundkid
Copy link

I can see why the esbuild team might not want to commit to an external API now, but I think accepting #153 is pretty much a no-brainer, since it doesn't add any new API surface but makes the existing CLI interface easier to use.

@evanw
Copy link
Owner

evanw commented May 27, 2020

Not to get ahead of myself here, but for this to be practical/usable for Hugo, we would need access to the filesystem/resolver API, i.e. something more powerful than the above.

Can you say what your requirements would be explicitly? That could help inform the discussion.

I could see exposing a Go-based transform API to mirror the existing JavaScript-based API. That would let you use esbuild as a minifier or as a way to convert JSX/TypeScript to JavaScript. It's essentially the same as the stable stdin/stdout command-line interface but exposed such that you don't need to touch the file system.

@bep
Copy link
Author

bep commented May 27, 2020

Can you say what your requirements would be explicitly?

My main requirement that differs from the obvious is this: Hugo is backed by a Afero union filesystem. JavaScript source files (and other source files) will be mounted to virtual roots that does not match their location on the real file system (you can even mount GitHub repositories). As an example: For LibSASS we get around this by providing an "import resolver" function to LibSASS.

For this project, my initial thinking that if there was an API that allowed me to implement this interface:

type FS interface {
	ReadDirectory(path string) map[string]Entry
	ReadFile(path string) (string, bool)
}

Or something, that would work. I can probably come up with a quick prototype to see if this will even work.

As to mirroring the JavaScript stdin/stdout CLI I assume you don't mean to actually use stdin/stdout. I notice you say in the README that "Go is just an implementation detail", but you do throw away some major wins (at least from my perspective) if you, for a Go API, trade out io.Reader etc. with os/exec. If you one day for some unlikely reason decide to rewrite the implementation in Rust or C, I would have no problem taking that loss/upgrade path.

I have browsed through the Go source code, and this is some very impressing work, especially considering the short commit history.

@evanw
Copy link
Owner

evanw commented Jun 11, 2020

There is now a Go API as of version 0.5.0. It's documented here. The new Go API exposes the same interface as the existing JavaScript API, so it can run a build and transform an individual file.

I'm planning to wait on more advanced integrations such as intercepting file system access until a plugin API is exposed. You can follow #111 for updates about the plugin API as it develops. It will probably be a while before that falls into place though. I want to get code splitting and a CSS loader in place first before I implement a plugin API on top.

@rizrmd
Copy link

rizrmd commented Jul 5, 2020

There is now a Go API as of version 0.5.0. It's documented here. The new Go API exposes the same interface as the existing JavaScript API, so it can run a build and transform an individual file.

I'm planning to wait on more advanced integrations such as intercepting file system access until a plugin API is exposed. You can follow #111 for updates about the plugin API as it develops. It will probably be a while before that falls into place though. I want to get code splitting and a CSS loader in place first before I implement a plugin API on top.

Umm... linked documentation is missing, but I found godoc here

@evanw
Copy link
Owner

evanw commented Jul 5, 2020

Whoops, sorry about that. The community asked me to move it to godoc and I forgot to update my link above.

@appcypher
Copy link

@evanw There is a go api and that's awesome, but there is still no way of implementing a file system interface like @bep suggested in this thread.

There are cases where one needs to create an abstraction over the file system. @bep's virtual fs is one case, in my case I have a capability-based system that guards how files are accessed, so I can't let esbuild go wild during import resolution.

@evanw
Copy link
Owner

evanw commented Oct 12, 2021

there is still no way of implementing a file system interface

Why not just write a plugin that intercepts and handles all paths? You can either return file contents for a valid path or an error if the path is invalid. Documentation for esbuild's plugin API is here: https://esbuild.github.io/plugins/.

@bep
Copy link
Author

bep commented Oct 12, 2021

Why not just write a plugin that intercepts and handles all paths?

I see my name mentioned above. I (in Hugo) have imported a custom import resolver and it works great. We handle paths we know about and then delegate to esbuild for the hard stuff (aka node_modules).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants