diff --git a/crates/backend/src/typegen.rs b/crates/backend/src/typegen.rs index 350fb9c9..81f9fdf0 100644 --- a/crates/backend/src/typegen.rs +++ b/crates/backend/src/typegen.rs @@ -2,6 +2,8 @@ mod r#enum; mod r#fn; mod r#struct; +use std::collections::HashMap; + use once_cell::sync::Lazy; use quote::ToTokens; use regex::Regex; @@ -27,8 +29,16 @@ pub trait ToTypeDef { fn to_type_def(&self) -> TypeDef; } -pub static VEC_REGEX: Lazy = Lazy::new(|| Regex::new(r"^Vec < (.*) >$").unwrap()); -pub static OPTION_REGEX: Lazy = Lazy::new(|| Regex::new(r"^Option < (.*) >").unwrap()); +pub static TYPE_REGEXES: Lazy> = Lazy::new(|| { + let mut map = HashMap::default(); + map.extend([ + ("Vec", Regex::new(r"^Vec < (.*) >$").unwrap()), + ("Option", Regex::new(r"^Option < (.*) >").unwrap()), + ("Result", Regex::new(r"^Result < (.*) >").unwrap()), + ]); + + map +}); pub fn ty_to_ts_type(ty: &Type) -> String { match ty { @@ -54,6 +64,7 @@ pub fn ty_to_ts_type(ty: &Type) -> String { pub fn str_to_ts_type(ty: &str) -> String { match ty { + "()" => "null".to_owned(), "i8" | "i16" | "i32" | "i64" | "u8" | "u16" | "u32" => "number".to_owned(), "i128" | "isize" | "u64" | "u128" | "usize" => "BigInt".to_owned(), "bool" => "boolean".to_owned(), @@ -61,18 +72,24 @@ pub fn str_to_ts_type(ty: &str) -> String { "Object" => "object".to_owned(), // nothing but `& 'lifetime str` could ends with ` str` s if s.ends_with(" str") => "string".to_owned(), - s if s.starts_with("Vec") && VEC_REGEX.is_match(s) => { - let captures = VEC_REGEX.captures(s).unwrap(); + s if s.starts_with("Vec") && TYPE_REGEXES["Vec"].is_match(s) => { + let captures = TYPE_REGEXES["Vec"].captures(s).unwrap(); let inner = captures.get(1).unwrap().as_str(); format!("Array<{}>", str_to_ts_type(inner)) } - s if s.starts_with("Option") && OPTION_REGEX.is_match(s) => { - let captures = OPTION_REGEX.captures(s).unwrap(); + s if s.starts_with("Option") && TYPE_REGEXES["Option"].is_match(s) => { + let captures = TYPE_REGEXES["Option"].captures(s).unwrap(); let inner = captures.get(1).unwrap().as_str(); format!("{} | undefined", str_to_ts_type(inner)) } + s if s.starts_with("Result") && TYPE_REGEXES["Result"].is_match(s) => { + let captures = TYPE_REGEXES["Result"].captures(s).unwrap(); + let inner = captures.get(1).unwrap().as_str(); + + format!("Error | {}", str_to_ts_type(inner)) + } s => s.to_owned(), } } diff --git a/examples/napi/__test__/typegen.spec.ts.md b/examples/napi/__test__/typegen.spec.ts.md index 24d4b7e7..b17746ee 100644 --- a/examples/napi/__test__/typegen.spec.ts.md +++ b/examples/napi/__test__/typegen.spec.ts.md @@ -12,6 +12,7 @@ Generated by [AVA](https://avajs.dev). export function getNums(): Array␊ export function sumNums(nums: Array): number␊ export function getCwd(callback: (arg0: string) => void): void␊ + export function readFile(callback: (arg0: Error | null, arg1: string | undefined) => void): void␊ export enum Kind { Dog = 0, Cat = 1, Duck = 2 }␊ export enum CustomNumEnum { One = 1, Two = 2, Three = 3, Four = 4, Six = 6, Eight = 8, Nine = 9, Ten = 10 }␊ export function enumToI32(e: CustomNumEnum): number␊ diff --git a/examples/napi/__test__/typegen.spec.ts.snap b/examples/napi/__test__/typegen.spec.ts.snap index 12512286..81dd14dd 100644 Binary files a/examples/napi/__test__/typegen.spec.ts.snap and b/examples/napi/__test__/typegen.spec.ts.snap differ diff --git a/examples/napi/__test__/values.spec.ts b/examples/napi/__test__/values.spec.ts index f2aed855..f87f1144 100644 --- a/examples/napi/__test__/values.spec.ts +++ b/examples/napi/__test__/values.spec.ts @@ -18,6 +18,7 @@ import { listObjKeys, createObj, mapOption, + readFile, } from '../' test('number', (t) => { @@ -78,6 +79,11 @@ test('callback', (t) => { null, 'Expect value to be Function, but received Undefined', ) + + readFile((err, content) => { + t.is(err, null) + t.is(content, 'hello world') + }) }) test('object', (t) => { diff --git a/examples/napi/index.d.ts b/examples/napi/index.d.ts index a869439a..7cdb1527 100644 --- a/examples/napi/index.d.ts +++ b/examples/napi/index.d.ts @@ -2,6 +2,7 @@ export function getWords(): Array export function getNums(): Array export function sumNums(nums: Array): number export function getCwd(callback: (arg0: string) => void): void +export function readFile(callback: (arg0: Error | null, arg1: string | undefined) => void): void export enum Kind { Dog = 0, Cat = 1, Duck = 2 } export enum CustomNumEnum { One = 1, Two = 2, Three = 3, Four = 4, Six = 6, Eight = 8, Nine = 9, Ten = 10 } export function enumToI32(e: CustomNumEnum): number diff --git a/examples/napi/src/callback.rs b/examples/napi/src/callback.rs index ceff82b4..2fe4c926 100644 --- a/examples/napi/src/callback.rs +++ b/examples/napi/src/callback.rs @@ -5,3 +5,18 @@ use std::env; fn get_cwd Result<()>>(callback: T) { callback(env::current_dir().unwrap().to_string_lossy().to_string()).unwrap(); } + +/// napi = { version = 2, features = ["serde-json"] } +#[napi] +fn read_file, Option) -> Result<()>>(callback: T) { + match read_file_content() { + Ok(s) => callback(Ok(()), Some(s)), + Err(e) => callback(Err(e), None), + } + .unwrap(); +} + +fn read_file_content() -> Result { + // serde_json::from_str(&s)?; + Ok("hello world".to_string()) +}