diff --git a/src/lib.rs b/src/lib.rs index 91a6296..9860fc9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -65,7 +65,7 @@ where /// Generate frontend TypeScript API client from the API routes. pub fn generate_client>(&self, path: P) -> Result<(), String> { - let fetch_api_function = r#" async function fetchApi(endpoint: string, options: RequestInit): Promise { + let fetch_api_function = r#" async function fetch_api(endpoint: string, options: RequestInit): Promise { const response = await fetch(endpoint, { headers: { "Content-Type": "application/json", @@ -75,6 +75,18 @@ where }); return response.json(); } + + function query_str(params: Record): string { + if (params) { + let data: Record = {}; + for (let key in params) { + if (params[key] != null) data[key] = params[key].toString(); + } + // the URLSearchParams escapes any problematic values + return '?' + new URLSearchParams(data).toString(); + } + return ''; + } "#; let namespace_start = "namespace api {\n"; let namespace_end = "}\n\nexport default api;"; @@ -253,13 +265,12 @@ fn generate_ts_function( url += "?"; url += "${new URLSearchParams(queryMap).toString()}"; } else if params_str.contains("query") { - url += "?"; - url += "${encodeURIComponent(query)}"; + url += "${query_str(query)}"; } format!( r#" export async function {fn_name}({params_str}): Promise<{response_type}> {{ - return fetchApi(`{url}`, {{ + return fetch_api(`{url}`, {{ method: "{method}", {body_assignment} }}); }} diff --git a/tests/api.ts b/tests/api.ts index bbf2024..52abb7e 100644 --- a/tests/api.ts +++ b/tests/api.ts @@ -16,7 +16,7 @@ namespace api { huh: T; } - async function fetchApi(endpoint: string, options: RequestInit): Promise { + async function fetch_api(endpoint: string, options: RequestInit): Promise { const response = await fetch(endpoint, { headers: { "Content-Type": "application/json", @@ -27,15 +27,27 @@ namespace api { return response.json(); } + function query_str(params: Record): string { + if (params) { + let data: Record = {}; + for (let key in params) { + if (params[key] != null) data[key] = params[key].toString(); + } + // the URLSearchParams escapes any problematic values + return '?' + new URLSearchParams(data).toString(); + } + return ''; + } + export async function add_root(path: number, data: Hello, string>, string>): Promise { - return fetchApi(`/${encodeURIComponent(path)}`, { + return fetch_api(`/${encodeURIComponent(path)}`, { method: "POST", body: JSON.stringify(data) }); } export async function fetch_root(queryMap: Record, path: number): Promise { - return fetchApi(`/${encodeURIComponent(path)}?${new URLSearchParams(queryMap).toString()}`, { + return fetch_api(`/${encodeURIComponent(path)}?${new URLSearchParams(queryMap).toString()}`, { method: "GET", }); }