Feature request: using inventory to build custom bindings
Opened this issue · 0 comments
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 collect
s 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.