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

Generate Typescript Declaration Modules and Stubs #2

Merged
merged 27 commits into from
Jun 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
8d5d28b
unit test setup
nicoburniske Jun 17, 2024
fda9da3
kind of working stubgen
nicoburniske Jun 17, 2024
604ec15
before custom export
nicoburniske Jun 17, 2024
b7295e4
fix module names
nicoburniske Jun 17, 2024
273c770
move more functions to printer
nicoburniske Jun 17, 2024
56b1da5
simplify generate_interface
nicoburniske Jun 17, 2024
bf8bc7d
improve guest interface generation
nicoburniske Jun 18, 2024
daf6329
everything working guest generation except resources
nicoburniske Jun 18, 2024
51f4e71
add interface definitions for resource exports
nicoburniske Jun 18, 2024
ccc2d83
improve unit test
nicoburniske Jun 18, 2024
19897a1
test and resource interface improvements
nicoburniske Jun 18, 2024
fdebdd7
remove unused and todo
nicoburniske Jun 18, 2024
0091edb
more unit test
nicoburniske Jun 18, 2024
17e62f3
stubgen import test
nicoburniske Jun 18, 2024
fdb6899
rpc tests
nicoburniske Jun 18, 2024
53d6d59
remove push + format in favor of uwrite! macros
nicoburniske Jun 18, 2024
e6fe9a7
rename base to instance
nicoburniske Jun 19, 2024
7aecd57
update lib exports
nicoburniske Jun 19, 2024
4970671
integrate command into jco cli
nicoburniske Jun 19, 2024
f8ca2bd
minor clippy warnings
nicoburniske Jun 19, 2024
232bdf7
allow inline interface
nicoburniske Jun 19, 2024
fe03a51
use anyhow instead of unimplemented panic
nicoburniske Jun 19, 2024
8412740
improve stubgen rpc test to use common types
nicoburniske Jun 19, 2024
b8542a0
cargo fmt
nicoburniske Jun 19, 2024
4b871c6
replace Guest with World
nicoburniske Jun 19, 2024
2fc0781
remove nested TsInterface definition and make resource processing exp…
nicoburniske Jun 19, 2024
196454b
clippy fixes
nicoburniske Jun 19, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 45 additions & 28 deletions crates/js-component-bindgen-component/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ use std::path::PathBuf;

use anyhow::{Context, Result};
use js_component_bindgen::{
generate_types,
source::wit_parser::{Resolve, UnresolvedPackage},
generate_types, generate_typescript_stubs,
source::wit_parser::{PackageId, Resolve, UnresolvedPackage},
transpile,
};

Expand Down Expand Up @@ -116,32 +116,8 @@ impl Guest for JsComponentBindgenComponent {
name: String,
opts: TypeGenerationOptions,
) -> Result<Vec<(String, Vec<u8>)>, String> {
let mut resolve = Resolve::default();
let id = match opts.wit {
Wit::Source(source) => {
let pkg = UnresolvedPackage::parse(&PathBuf::from(format!("{name}.wit")), &source)
.map_err(|e| e.to_string())?;
resolve.push(pkg).map_err(|e| e.to_string())?
}
Wit::Path(path) => {
let path = PathBuf::from(path);
if path.is_dir() {
resolve.push_dir(&path).map_err(|e| e.to_string())?.0
} else {
let contents = std::fs::read(&path)
.with_context(|| format!("failed to read file {path:?}"))
.map_err(|e| e.to_string())?;
let text = match std::str::from_utf8(&contents) {
Ok(s) => s,
Err(_) => return Err("input file is not valid utf-8".into()),
};
let pkg = UnresolvedPackage::parse(&path, text).map_err(|e| e.to_string())?;
resolve.push(pkg).map_err(|e| e.to_string())?
}
}
Wit::Binary(_) => todo!(),
};

let (resolve, id) =
resolve_package(opts.wit, Some(name.as_str())).map_err(|e| e.to_string())?;
let world_string = opts.world.map(|world| world.to_string());
let world = resolve
.select_world(id, world_string.as_deref())
Expand All @@ -166,4 +142,45 @@ impl Guest for JsComponentBindgenComponent {

Ok(files)
}

fn generate_typescript_stubs(opts: TypescriptStubOptions) -> Result<Files, String> {
let (resolve, id) = resolve_package(opts.wit, None).map_err(|e| e.to_string())?;
let world_string = opts.world.map(|world| world.to_string());
let world = resolve
.select_world(id, world_string.as_deref())
.map_err(|e| e.to_string())?;

let files = generate_typescript_stubs(resolve, world).map_err(|e| e.to_string())?;

Ok(files)
}
}

fn resolve_package(wit_opt: Wit, name: Option<&str>) -> Result<(Resolve, PackageId)> {
let mut resolve = Resolve::default();
let id = match wit_opt {
Wit::Source(source) => {
let name = name.unwrap_or("world");
let pkg = UnresolvedPackage::parse(&PathBuf::from(format!("{name}.wit")), &source)?;
resolve.push(pkg)?
}
Wit::Path(path) => {
let path = PathBuf::from(path);
if path.is_dir() {
resolve.push_dir(&path)?.0
} else {
let contents = std::fs::read(&path)
.with_context(|| format!("failed to read file {path:?}"))?;
let text = match std::str::from_utf8(&contents) {
Ok(s) => s,
Err(_) => anyhow::bail!("input file is not valid utf-8"),
};
let pkg = UnresolvedPackage::parse(&path, text)?;
resolve.push(pkg)?
}
}
Wit::Binary(_) => todo!(),
};

Ok((resolve, id))
}
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,13 @@ world js-component-bindgen {
map: option<maps>,
}

record typescript-stub-options {
/// wit to generate typing from
wit: wit,
/// world to generate typing for
%world: option<string>,
}

enum export-type {
function,
instance,
Expand All @@ -100,4 +107,6 @@ world js-component-bindgen {
export generate: func(component: list<u8>, options: generate-options) -> result<transpiled, string>;

export generate-types: func(name: string, options: type-generation-options) -> result<files, string>;

export generate-typescript-stubs: func(options: typescript-stub-options) -> result<files, string>;
}
11 changes: 10 additions & 1 deletion crates/js-component-bindgen/src/files.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,16 @@ impl Files {
self.files.remove(name)
}

pub fn iter(&self) -> impl Iterator<Item = (&'_ str, &'_ [u8])> {
pub fn iter(&self) -> impl Iterator<Item = (&str, &[u8])> {
self.files.iter().map(|p| (p.0.as_str(), p.1.as_slice()))
}
}

impl IntoIterator for Files {
type Item = (String, Vec<u8>);
type IntoIter = std::collections::btree_map::IntoIter<String, Vec<u8>>;

fn into_iter(self) -> Self::IntoIter {
self.files.into_iter()
}
}
18 changes: 13 additions & 5 deletions crates/js-component-bindgen/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ mod core;
mod files;
mod transpile_bindgen;
mod ts_bindgen;
mod ts_stubgen;

pub mod esm_bindgen;
pub mod function_bindgen;
Expand Down Expand Up @@ -70,11 +71,18 @@ pub fn generate_types(

ts_bindgen(&name, &resolve, world_id, &opts, &mut files);

let mut files_out: Vec<(String, Vec<u8>)> = Vec::new();
for (name, source) in files.iter() {
files_out.push((name.to_string(), source.to_vec()));
}
Ok(files_out)
Ok(files.into_iter().collect())
}

pub fn generate_typescript_stubs(
resolve: Resolve,
world_id: WorldId,
) -> Result<Vec<(String, Vec<u8>)>, anyhow::Error> {
let mut files = files::Files::default();

ts_stubgen::ts_stubgen(&resolve, world_id, &mut files)?;

Ok(files.into_iter().collect())
}

/// Generate the JS transpilation bindgen for a given Wasm component binary
Expand Down
6 changes: 6 additions & 0 deletions crates/js-component-bindgen/src/source.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,12 @@ impl From<Source> for String {
}
}

impl AsRef<str> for Source {
fn as_ref(&self) -> &str {
&self.s
}
}

#[cfg(test)]
mod tests {
use super::Source;
Expand Down
Loading
Loading