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

Feature request: using inventory to build custom bindings #370

Open
karambarakat opened this issue Nov 25, 2024 · 0 comments
Open

Feature request: using inventory to build custom bindings #370

karambarakat opened this issue Nov 25, 2024 · 0 comments
Labels
enhancement New feature or request

Comments

@karambarakat
Copy link

Is your feature request related to a problem? Please describe.
sometimes, I want to customize the way this crate generates bindings.

Describe alternatives you've considered
One of the alternatives is CLI issue #304, and I like it, but this is more versatile and is easier to implement.

Note
if this is something you would like to merge I can start working on it

Describe the solution you'd like
This feature relies on the inventory crate. The idea is that the derive macro submit inventory item describes how a given type can be converted to typescript binding; then, I can add a custom executable in the bin folder that collects these inventory items and generate these binding or run arbitrary code.

This is what I will add to the ts-rs crate:

pub trait DynTS { ... }

// this trait closely mimics TS trait but allows for dynamic behavior
impl<T> DynTS for PhantomData<T> where T: TS { ... }

pub struct Submittable {
    init: fn () -> Box<dyn DynTS>
}

inventory::collect!{ Submittable }

This is what derive macro will generate:

use ts_rs::*;

#[derive(TS)] 
struct MyType { ... }

impl ts_rs::TS for MyType { ... }

inventory::submit! { Submittable {
    init: || Box::new(PhantomData::<MyType>)
}}

Here is an example of bin/generate_ts.rs:

fn strategy_1() { 
    // Create the `binding` folder if it does not exist 
    let path = Path::new("binding"); 
    if !path.exists() { 
        fs::create_dir(path).expect("Failed to create `binding` directory"); } 
        // Iterate through all `Submitable` items 
        for submit in inventory::iter::<Submittable> { 
            // Initialize the DynTS object 
            let dyn_ts: Box<dyn DynTS> = (submit.init)(); 

            // Generate TypeScript binding 
            let ts_binding = dyn_ts.declare(); 

            // Determine file name 
            let type_name = ts_binding.split_whitespace().next().unwrap_or("unknown"); 
            
            // Extract type name 
            let file_name = format!("binding/type_{}.ts", type_name); 

            // Write the TS binding to the file 
            let mut file = File::create(&file_name).expect("Failed to create file"); 
            writeln!(file, "{}", ts_binding).expect("Failed to write to file"); 
        } 
}
fn main() {
    strategy_1()
}

The good thing here is that you can add this strategy to cli, or other people can copy it and customize it to their need.

@karambarakat karambarakat added the enhancement New feature or request label Nov 25, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

1 participant