Skip to content

feat: Auto-generate TS bindings#140

Merged
GeckoEidechse merged 10 commits intomainfrom
feat/autogenerate-ts-bindings
Feb 5, 2023
Merged

feat: Auto-generate TS bindings#140
GeckoEidechse merged 10 commits intomainfrom
feat/autogenerate-ts-bindings

Conversation

@GeckoEidechse
Copy link
Copy Markdown
Member

@GeckoEidechse GeckoEidechse commented Jan 19, 2023

That way instead of manually duplicating code, we can just run cargo test to generate them using ts-rs.

Closes #126

That way instead of manually duplicating code, we can just run
`cargo test` to generate them.
@GeckoEidechse
Copy link
Copy Markdown
Member Author

I assume we probably also wanna commit the generated bindings so that we can keep track of them (and might even be required for build to succeed).

@Alystrasz thoughts?

TypeScript binding autogenerated from Rust code
TypeScript binding autogenerated from Rust code
@GeckoEidechse GeckoEidechse marked this pull request as ready for review January 19, 2023 21:46
@GeckoEidechse
Copy link
Copy Markdown
Member Author

Aight, the only thing missing is GameInstall and InstallType but I'm struggling with getting InstallType working and that's a dependency for GameInstall.

Given that I could use this PR for #139 (otherwise I'll have even more duplicated definitions), I'd just merge what we hav here and keep GameInstall and InstallType duplicated ^^

@GeckoEidechse
Copy link
Copy Markdown
Member Author

Added docs as well now ^^

Now it should be done for real :P

GeckoEidechse added a commit that referenced this pull request Jan 20, 2023
@Alystrasz
Copy link
Copy Markdown
Collaborator

I assume we probably also wanna commit the generated bindings so that we can keep track of them (and might even be required for build to succeed).

We want to avoid people modifying TS bindings instead of Rust classes (despite your documentation saying not to :))
Is there a way to generate bindings just before building? We'd have issues with Typescript linting during development though...

@GeckoEidechse
Copy link
Copy Markdown
Member Author

We want to avoid people modifying TS bindings instead of Rust classes (despite your documentation saying not to :))

Uh, I don't quite see where I tell the reader to modify them. I just tell them how to (re-)generate the bindings if changes to the corresponding Rust class were made. Or am I misunderstanding something? ^^

Is there a way to generate bindings just before building? We'd have issues with Typescript linting during development though...

We can create them just before building by simply running cargo test as a prerequesite step when running npx tauri dev/npx tauri build. The issue with that approach however is that running cargo test takes some time to complete and once we add unit tests the runtime of cargo test will only increase. So given our long compile time, this is probably not a preferred approach.

AFAIK it is possible to only run certain unit tests but the way ts-rs exposes them means any new binding added will require modifying the list of specific tests to run.

Therefore the best approach is probably to check in CI if running cargo test modified any files in the bindings/ folder as that implies that someone either committed a manually changed version or forgot to commit a new binding (though the latter would already fail in CI anyway).

Question is, do I have to do this in this PR still or can I just make a TODO issue and do it in the next PR? ^^"

@Alystrasz
Copy link
Copy Markdown
Collaborator

Uh, I don't quite see where I tell the reader to modify them. I just tell them how to (re-)generate the bindings if changes to the corresponding Rust class were made. Or am I misunderstanding something? ^^

Nah, documentation tells developers to edit Rust classes, and not bindings.

We can create them just before building by simply running cargo test as a prerequesite step when running npx tauri dev/npx tauri build.

Can we integrate bindings generation in the file watcher (i.e. if you update a Rust class while running npx tauri dev, typescript file is updated as well)?

Question is, do I have to do this in this PR still or can I just make a TODO issue and do it in the next PR? ^^"

We already have a bunch of issues, let's do this here :)

@GeckoEidechse
Copy link
Copy Markdown
Member Author

We can create them just before building by simply running cargo test as a prerequesite step when running npx tauri dev/npx tauri build.

Can we integrate bindings generation in the file watcher (i.e. if you update a Rust class while running npx tauri dev, typescript file is updated as well)?

File watcher stuff is handled by Tauri. I'm not aware of a way to hook that to add a call to a custom function on file change. And even then as soon as we start doing unit testing, it would mean that all unit tests are re-run the moment any time the developer presses save on a file. That's a lot of additional compute needed that not everyone has (e.g. me when working on FlightCore on my puny laptop :P)

@GeckoEidechse
Copy link
Copy Markdown
Member Author

Question is, do I have to do this in this PR still or can I just make a TODO issue and do it in the next PR? ^^"

We already have a bunch of issues, let's do this here :)

Welp, guess I have to figure out how to actually do this in CI then ^^"

Checks for uncommitted binding changes in CI and fails if they differ
@GeckoEidechse
Copy link
Copy Markdown
Member Author

Question is, do I have to do this in this PR still or can I just make a TODO issue and do it in the next PR? ^^"

We already have a bunch of issues, let's do this here :)

Welp, guess I have to figure out how to actually do this in CI then ^^"

Turns out using ChatGPT this was actually easier than I anticipated. Anyway done with 49c454a now. Also did a few test runs to ensure that it fails if binding changes are not committed ^^

@GeckoEidechse
Copy link
Copy Markdown
Member Author

GeckoEidechse commented Feb 3, 2023

To add some more context to this PR, I did some more research into TypeScript interfaces generated from Rust.

Compared to ts-rs, alternatives are:

  • wasm-bindgen which appears to only do JS not TS. Also more aimed at WASM, so not a better alternative
  • typescript-definitions saw no update in 4 years, so I rather not use it and have it break in the future, so not a better alternative
  • Using schemars as described here. Also looks a lot more cumbersome to use (build TypeScript type at runtime from JSON schema), so not a better alternative
  • tauri-bindgen-ts might be a higher level library but it's WIP in alpha with no commits since 4 months ago. Further it just uses ts-rs in the background, so again not (currently) a better "alternative".

Hence I'd argue that ts-rs is the best choice here ^^

@GeckoEidechse
Copy link
Copy Markdown
Member Author

And as for generating bindings, I'd argue that committing generated bindings is the way to go as otherwise TypeScript linting will fail until running cargo test at least once which requires a mostly compiled codebase (and will take even longer once we add unit tests) and we have CI in place to catch any issues regarding uncommitted (changed) bindings or accidentally committed WIP test bindings ^^

@GeckoEidechse GeckoEidechse added the high priority High priority issue or PR label Feb 4, 2023
Copy link
Copy Markdown
Collaborator

@Alystrasz Alystrasz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm unsure about committing bindings to repo, maybe I'll rework that later.

@GeckoEidechse GeckoEidechse merged commit 802d7df into main Feb 5, 2023
@GeckoEidechse GeckoEidechse deleted the feat/autogenerate-ts-bindings branch February 5, 2023 14:53
Alystrasz added a commit that referenced this pull request Mar 2, 2023
* feat: Initial backend code to get list of PRs

Hardcoded for launcher right now

* refactor: Autogen TS bindings from Rust code
using `ts-rs` as done in #140

* fix: Fix incorrect typing

What is returned is actually an array of `PullsApiResponseElement`

* feat: Prototyping frontend UI for installing PR

* fix: Use right repo

Used Mods instead of Launcher

* feat: Enable installing launcher pull request

* refactor: Rename variables to indicate approp repo

NorthstarLauncher vs NorthstarMods

* style: Formatting fixes

* feat: Initial code for getting mods PRs

* feat: Add backend code for installing mods PRs

* feat: Add note about launching in notification

* fix: Remove commented out code

* refactor: Depduplicate code

* refactor: Remove unnecessary use of anyhow

* refactor: Use already existing function
for checking game path

* feat: Add comment about profile / batch file

* chore: Remove leftover print statements

* feat: Add clickable link for each PR

* refactor: Reduce duplicate code

* refactor: Rename enum

* fix: Use proper type

* fix: Remove leftover `console.log`s

* style: Revert accidental formatting change

* refactor: Remove second API call for mods PRs

* refactor: Rename variable

* refactor: Remove second API call for launcher PRs

* refactor: Move API URL string to `constants.rs`

So that all constants are in a single place

* fix: Restore lines deleted in merge

* style: Formatting fixes

* fix: Print line when done installing PR

* feat: Show notification for install start/done

Displays a notification that PR install has started and upon completion
replaces it with one saying that install has completed.

* fix: Remove left-over console log

* feat: "Install PR" UI (#197)

* refactor: export pull requests selector to dedicated component

* refactor: regroup launcher+mods collapses in one collapse component

* refactor: load pull requests when opening selector collapse item

* refactor: review progress loaders' style

* fix: don't fetch PRs if they've already been loaded

* feat: update collapse style

* refactor: remove fetch success notification

* refactor: both collapses can be opened at the same time

* fix: non-accordion collapse sends an object as event parameter

* fix: Iterate over multiple pages of GitHub CI API
This ensures we can still grab older artifacts.

Max page is capped at 10 as going too high will cause us to hit API rate
limits.

Also refined error message accordingly.

* refactor: Move stored PRs to submodule
as suggested in review

* refactor: Move getPullRequests to store submodule

I order to clean up PullRequestSelector.vue

Other functions will follow in separate commits.

Currently TypeScript compilation fails on undefined type of `state`

* fix: Properly define state type

* refactor: Move installLauncherPR to store submodule

* refactor: Move installModsPR to store submodule

---------

Co-authored-by: Rémy Raes <contact@remyraes.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

high priority High priority issue or PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Auto-generate TypeScript interfaces from Rust objects

2 participants