-
Notifications
You must be signed in to change notification settings - Fork 1.8k
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
Add support for Typescript in Rust Relay compiler #3182
Add support for Typescript in Rust Relay compiler #3182
Conversation
… different language can be inserted.
Awesome! I took a quick look through and the high-level approach makes sense, of having typegen create an abstract AST of types and then having Flow/TS-specific writers to convert that AST to code. Thanks for the contribution! I'll leave to @tyao1, @kassens, and @rbalicki2 for review |
This is so cool, awesome work @MaartenStaa ! 😍 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@kassens has imported this pull request. If you are a Facebook employee, you can view this diff on Phabricator.
// Ending in *.js or *.ts depending on the project lanague. | ||
Expr::Suffix(vec![match &p.typegen_config.language { | ||
TypegenLanguage::Flow => "js", | ||
TypegenLanguage::Typescript => "ts", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
with react, this has to be tsx
. So could this be an array perhaps?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right, I adjusted it! I set it to look at .jsx as well, just in case people use that.
Edit: I committed this on my phone and see that it doesn't compile. I'll have to take a look at that later. I'm on vacation now so a bit limited.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@maraisr Fixed the build now as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
First, I want to repeat everyone here and say this is awesome and pretty much aligns with how I thought it'd be done ideally.
Did you come up with the way the fragment references are modeled in typescript or was this based on the existing (community driven) typescript types? I know this was pretty tricky to get right in Flow.
|
||
impl Default for TypegenLanguage { | ||
fn default() -> Self { | ||
Self::Flow |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was even thinking of making Typescript the default, but just realized *.ts
files wouldn't work with vanilla JS anymore. The Flow generated *.js
files using Flow comment style syntax allows people to just treat them as pure JS files.
Maybe we could even make this optional and skip generating types altogether to make the files a bit smaller.
Expr::Suffix(match &p.typegen_config.language { | ||
TypegenLanguage::Flow => vec![PathBuf::from("js"), PathBuf::from("jsx")], | ||
TypegenLanguage::Typescript => { | ||
vec![PathBuf::from("ts"), PathBuf::from("tsx")] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For a TS project, I suppose you'd have all your own product code in *.tsx?
files or should this also include .js
files for hybrid projects?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think generally its all ts or all js. But can't presume that, so think yeah maybe hybrids are nice?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@kassens has imported this pull request. If you are a Facebook employee, you can view this diff on Phabricator.
Awesome, very nice to see this @MaartenStaa 👏 |
readonly $fragmentRefs: RecursiveFragment$ref, | ||
}; | ||
------------------------------------------------------------------------------- | ||
import type { PhotoFragment$ref } from "PhotoFragment.graphql"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be better to avoid any need to import these types, as that entirely removes the need to have a single artefact directory (or Haste). See for example this output of the existing TS plugin.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah... I think this is actually a blocker for a merge. Typescript wouldn't know what that means (please correct me here).
At the very least just prefix with a ./
,
-import type { PhotoFragment$ref } from "PhotoFragment.graphql";
+import type { PhotoFragment$ref } from "./PhotoFragment.graphql";
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, yeah that’s a good point. @kassens can you amend that in your import?
Given the above, I'm somewhat inclined to merge this and have it open up for contributions to tweak the output in follow up PRs. Thoughts? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@kassens has imported this pull request. If you are a Facebook employee, you can view this diff on Phabricator.
Yeah @kassens I think that is a great way forward. Also a great way for non-Rust contributors to have a go, as is not as daunting as starting something from scratch. (Mind you @MaartenStaa did just that 😛). I'm super keen to investigate a cleaner named interface, and proper union types. And think it was outlined in another ticket already, around not merging unions and forcing things to be nullable. |
readonly $fragmentRefs: ConditionField$ref, | ||
}; | ||
------------------------------------------------------------------------------- | ||
import { FragmentReference } from "relay-runtime"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
think though maybe this should import type {}
no?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not a requirement, but definitely something to follow up with.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@maraisr correct. It was a conscious decision to use this option since import type
was a relatively recent addition to Typescript, and I wouldn't want to make this unusable for people on older versions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The fragment reference import does currently use the type
keyword, though.
This sounds like a reasonable way to move forward, though I feel somewhat uneasy about having this merged at this stage since I wasn't able to test this yet.
To be fair, I have played around with Rust before in my spare time, so it's not like I dove in with zero experience.
I think you may be referring to my other PR, and how we ended up here in the first place: #3178. |
I think it would be ok to merge (with at least the relative import change) and then it would be good to port e.g. the TS example that exists in the TS plugin repo to use the rust compiler and then iterate on any issues and the few discussed here over the next few weeks. Others (e.g. me) can chime in too. As long as the relay team is ok with not putting out a public release until the dust has settled (@kassens ?). @MaartenStaa What do you think? |
For those of you coming here from google to fix this error: Watchman error: Watchman error: The watchman server reported an error: "failed to parse query: must use ["suffix", "suffixstring"]", while executing command I had to upgrade watchman brew upgrade watchman And restart watchman watchman shutdown-server |
See #3181 and #3180.
This PR adds a language option to the typegen_config and refactors the relay-typegen crate to allow completely different output based on the configured language, currently typescript and flow (which is the default when no language is configured, or an invalid one is set).
I also made some changes so the watchman query looks for .ts files when using typescript, and the output files also use .ts as their extension.
This probably needs a bit more work before it's completely ready. Off the top of my head:
relay-compiler/build_project/artifact_content.rs
some output is generated such as@flow
and a commented outimport type
statement? Those should probably be left out for Typescript.failed to parse query: must use ["suffix", "suffixstring"]
, and I don't have a clue why. This error was already returned before I made the changes to look for .ts files when using Typescript.relay-lsp
and whether any changes are needed there for Typescript.Looking forward to your feedback!
cc @kassens @josephsavona @maraisr