diff --git a/Cargo.lock b/Cargo.lock
index de7be79b6..197131bd6 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1321,6 +1321,12 @@ dependencies = [
"dtoa",
]
+[[package]]
+name = "dyn-clone"
+version = "1.0.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "545b22097d44f8a9581187cdf93de7a71e4722bf51200cfaba810865b49a495d"
+
[[package]]
name = "dyn-stack"
version = "0.10.0"
@@ -1875,6 +1881,19 @@ version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
+[[package]]
+name = "gloo-utils"
+version = "0.1.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "037fcb07216cb3a30f7292bd0176b050b7b9a052ba830ef7d5d65f6dc64ba58e"
+dependencies = [
+ "js-sys",
+ "serde",
+ "serde_json",
+ "wasm-bindgen",
+ "web-sys",
+]
+
[[package]]
name = "h2"
version = "0.3.24"
@@ -2364,6 +2383,15 @@ dependencies = [
"either",
]
+[[package]]
+name = "itertools"
+version = "0.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569"
+dependencies = [
+ "either",
+]
+
[[package]]
name = "itoa"
version = "0.4.8"
@@ -3028,6 +3056,17 @@ version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381"
+[[package]]
+name = "openapiv3"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cc02deea53ffe807708244e5914f6b099ad7015a207ee24317c22112e17d9c5c"
+dependencies = [
+ "indexmap 2.2.5",
+ "serde",
+ "serde_json",
+]
+
[[package]]
name = "openraft"
version = "0.9.1"
@@ -3115,6 +3154,7 @@ dependencies = [
"logos",
"once_cell",
"serde",
+ "tapi",
"thiserror",
"utoipa",
]
@@ -4300,6 +4340,28 @@ dependencies = [
"syn 2.0.52",
]
+[[package]]
+name = "serde_derive_internals"
+version = "0.28.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e578a843d40b4189a4d66bba51d7684f57da5bd7c304c64e14bd63efbef49509"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.52",
+]
+
+[[package]]
+name = "serde_derive_internals"
+version = "0.29.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "330f01ce65a3a5fe59a60c82f3c9a024b573b8a6e875bd233fe5f934e71d54e3"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.52",
+]
+
[[package]]
name = "serde_json"
version = "1.0.114"
@@ -4601,6 +4663,7 @@ dependencies = [
"serde_urlencoded",
"strum 0.26.2",
"tantivy",
+ "tapi",
"thiserror",
"tikv-jemallocator",
"tokenizers",
@@ -4919,6 +4982,36 @@ version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
+[[package]]
+name = "tapi"
+version = "0.1.0"
+dependencies = [
+ "axum",
+ "dyn-clone",
+ "futures-util",
+ "heck 0.4.1",
+ "indexmap 2.2.5",
+ "itertools 0.12.1",
+ "openapiv3",
+ "serde",
+ "serde_json",
+ "tapi-macro",
+ "tsify",
+]
+
+[[package]]
+name = "tapi-macro"
+version = "0.1.0"
+dependencies = [
+ "darling 0.20.8",
+ "heck 0.4.1",
+ "prettyplease",
+ "proc-macro2",
+ "quote",
+ "serde_derive_internals 0.29.0",
+ "syn 2.0.52",
+]
+
[[package]]
name = "tar"
version = "0.4.40"
@@ -5393,6 +5486,31 @@ version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
+[[package]]
+name = "tsify"
+version = "0.4.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d6b26cf145f2f3b9ff84e182c448eaf05468e247f148cf3d2a7d67d78ff023a0"
+dependencies = [
+ "gloo-utils",
+ "serde",
+ "serde_json",
+ "tsify-macros",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "tsify-macros"
+version = "0.4.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7a94b0f0954b3e59bfc2c246b4c8574390d94a4ad4ad246aaf2fb07d7dfd3b47"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "serde_derive_internals 0.28.0",
+ "syn 2.0.52",
+]
+
[[package]]
name = "twox-hash"
version = "1.6.3"
diff --git a/Cargo.toml b/Cargo.toml
index bf1fc0f1d..d4af37194 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -98,6 +98,7 @@ serde_json = "1.0.81"
serde_urlencoded = "0.7.1"
strum = { version = "0.26.2", features = ["derive"] }
tantivy = { git = "https://github.com/quickwit-oss/tantivy", rev = "182f58cea" }
+tapi = { path = "../tapi/crates/tapi/", package = "tapi", features = ["openapi"] }
thiserror = "1.0.31"
tikv-jemallocator = "0.5"
tokenizers = "0.13.2"
diff --git a/crates/client-wasm/Cargo.lock b/crates/client-wasm/Cargo.lock
index fad148cb8..166690d7c 100644
--- a/crates/client-wasm/Cargo.lock
+++ b/crates/client-wasm/Cargo.lock
@@ -2,6 +2,21 @@
# It is not intended for manual editing.
version = 3
+[[package]]
+name = "addr2line"
+version = "0.21.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb"
+dependencies = [
+ "gimli",
+]
+
+[[package]]
+name = "adler"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
+
[[package]]
name = "aho-corasick"
version = "1.1.2"
@@ -20,12 +35,93 @@ dependencies = [
"term",
]
+[[package]]
+name = "async-trait"
+version = "0.1.79"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a507401cad91ec6a857ed5513a2073c82a9b9048762b885bb98655b306964681"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.50",
+]
+
[[package]]
name = "autocfg"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
+[[package]]
+name = "axum"
+version = "0.7.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3a6c9af12842a67734c9a2e355436e5d03b22383ed60cf13cd0c18fbfe3dcbcf"
+dependencies = [
+ "async-trait",
+ "axum-core",
+ "bytes",
+ "futures-util",
+ "http",
+ "http-body",
+ "http-body-util",
+ "hyper",
+ "hyper-util",
+ "itoa",
+ "matchit",
+ "memchr",
+ "mime",
+ "percent-encoding",
+ "pin-project-lite",
+ "rustversion",
+ "serde",
+ "serde_json",
+ "serde_path_to_error",
+ "serde_urlencoded",
+ "sync_wrapper 1.0.0",
+ "tokio",
+ "tower",
+ "tower-layer",
+ "tower-service",
+ "tracing",
+]
+
+[[package]]
+name = "axum-core"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a15c63fd72d41492dc4f497196f5da1fb04fb7529e631d73630d1b491e47a2e3"
+dependencies = [
+ "async-trait",
+ "bytes",
+ "futures-util",
+ "http",
+ "http-body",
+ "http-body-util",
+ "mime",
+ "pin-project-lite",
+ "rustversion",
+ "sync_wrapper 0.1.2",
+ "tower-layer",
+ "tower-service",
+ "tracing",
+]
+
+[[package]]
+name = "backtrace"
+version = "0.3.71"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d"
+dependencies = [
+ "addr2line",
+ "cc",
+ "cfg-if",
+ "libc",
+ "miniz_oxide",
+ "object",
+ "rustc-demangle",
+]
+
[[package]]
name = "beef"
version = "0.5.2"
@@ -65,6 +161,18 @@ version = "3.15.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ea184aa71bb362a1157c896979544cc23974e08fd265f29ea96b59f0b4a555b"
+[[package]]
+name = "bytes"
+version = "1.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9"
+
+[[package]]
+name = "cc"
+version = "1.0.90"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5"
+
[[package]]
name = "cfg-if"
version = "1.0.0"
@@ -90,6 +198,41 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7"
+[[package]]
+name = "darling"
+version = "0.20.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "54e36fcd13ed84ffdfda6f5be89b31287cbb80c439841fe69e04841435464391"
+dependencies = [
+ "darling_core",
+ "darling_macro",
+]
+
+[[package]]
+name = "darling_core"
+version = "0.20.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9c2cf1c23a687a1feeb728783b993c4e1ad83d99f351801977dd809b48d0a70f"
+dependencies = [
+ "fnv",
+ "ident_case",
+ "proc-macro2",
+ "quote",
+ "strsim",
+ "syn 2.0.50",
+]
+
+[[package]]
+name = "darling_macro"
+version = "0.20.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f"
+dependencies = [
+ "darling_core",
+ "quote",
+ "syn 2.0.50",
+]
+
[[package]]
name = "diff"
version = "0.1.13"
@@ -117,6 +260,12 @@ dependencies = [
"winapi",
]
+[[package]]
+name = "dyn-clone"
+version = "1.0.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125"
+
[[package]]
name = "either"
version = "1.10.0"
@@ -150,6 +299,61 @@ version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
+[[package]]
+name = "form_urlencoded"
+version = "1.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456"
+dependencies = [
+ "percent-encoding",
+]
+
+[[package]]
+name = "futures-channel"
+version = "0.3.30"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78"
+dependencies = [
+ "futures-core",
+]
+
+[[package]]
+name = "futures-core"
+version = "0.3.30"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d"
+
+[[package]]
+name = "futures-macro"
+version = "0.3.30"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.50",
+]
+
+[[package]]
+name = "futures-task"
+version = "0.3.30"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004"
+
+[[package]]
+name = "futures-util"
+version = "0.3.30"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48"
+dependencies = [
+ "futures-core",
+ "futures-macro",
+ "futures-task",
+ "pin-project-lite",
+ "pin-utils",
+ "slab",
+]
+
[[package]]
name = "getrandom"
version = "0.2.12"
@@ -161,18 +365,130 @@ dependencies = [
"wasi",
]
+[[package]]
+name = "gimli"
+version = "0.28.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253"
+
+[[package]]
+name = "gloo-utils"
+version = "0.1.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "037fcb07216cb3a30f7292bd0176b050b7b9a052ba830ef7d5d65f6dc64ba58e"
+dependencies = [
+ "js-sys",
+ "serde",
+ "serde_json",
+ "wasm-bindgen",
+ "web-sys",
+]
+
[[package]]
name = "hashbrown"
version = "0.14.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604"
+[[package]]
+name = "heck"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
+
[[package]]
name = "hermit-abi"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bd5256b483761cd23699d0da46cc6fd2ee3be420bbe6d020ae4a091e70b7e9fd"
+[[package]]
+name = "http"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258"
+dependencies = [
+ "bytes",
+ "fnv",
+ "itoa",
+]
+
+[[package]]
+name = "http-body"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643"
+dependencies = [
+ "bytes",
+ "http",
+]
+
+[[package]]
+name = "http-body-util"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0475f8b2ac86659c21b64320d5d653f9efe42acd2a4e560073ec61a155a34f1d"
+dependencies = [
+ "bytes",
+ "futures-core",
+ "http",
+ "http-body",
+ "pin-project-lite",
+]
+
+[[package]]
+name = "httparse"
+version = "1.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904"
+
+[[package]]
+name = "httpdate"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
+
+[[package]]
+name = "hyper"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "186548d73ac615b32a73aafe38fb4f56c0d340e110e5a200bcadbaf2e199263a"
+dependencies = [
+ "bytes",
+ "futures-channel",
+ "futures-util",
+ "http",
+ "http-body",
+ "httparse",
+ "httpdate",
+ "itoa",
+ "pin-project-lite",
+ "smallvec",
+ "tokio",
+]
+
+[[package]]
+name = "hyper-util"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ca38ef113da30126bbff9cd1705f9273e15d45498615d138b0c20279ac7a76aa"
+dependencies = [
+ "bytes",
+ "futures-util",
+ "http",
+ "http-body",
+ "hyper",
+ "pin-project-lite",
+ "socket2",
+ "tokio",
+]
+
+[[package]]
+name = "ident_case"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
+
[[package]]
name = "indexmap"
version = "2.2.3"
@@ -192,7 +508,7 @@ checksum = "f23ff5ef2b80d608d61efee834934d862cd92461afc0560dedf493e4c033738b"
dependencies = [
"hermit-abi",
"libc",
- "windows-sys",
+ "windows-sys 0.52.0",
]
[[package]]
@@ -213,6 +529,15 @@ dependencies = [
"either",
]
+[[package]]
+name = "itertools"
+version = "0.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569"
+dependencies = [
+ "either",
+]
+
[[package]]
name = "itoa"
version = "1.0.10"
@@ -325,24 +650,76 @@ dependencies = [
"logos-codegen",
]
+[[package]]
+name = "matchit"
+version = "0.7.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94"
+
[[package]]
name = "memchr"
version = "2.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149"
+[[package]]
+name = "mime"
+version = "0.3.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
+
+[[package]]
+name = "miniz_oxide"
+version = "0.7.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7"
+dependencies = [
+ "adler",
+]
+
+[[package]]
+name = "mio"
+version = "0.8.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c"
+dependencies = [
+ "libc",
+ "wasi",
+ "windows-sys 0.48.0",
+]
+
[[package]]
name = "new_debug_unreachable"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54"
+[[package]]
+name = "object"
+version = "0.32.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441"
+dependencies = [
+ "memchr",
+]
+
[[package]]
name = "once_cell"
version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
+[[package]]
+name = "openapiv3"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cc02deea53ffe807708244e5914f6b099ad7015a207ee24317c22112e17d9c5c"
+dependencies = [
+ "indexmap",
+ "serde",
+ "serde_json",
+]
+
[[package]]
name = "optics"
version = "0.1.0"
@@ -353,6 +730,7 @@ dependencies = [
"logos",
"once_cell",
"serde",
+ "tapi",
"thiserror",
"utoipa",
]
@@ -380,6 +758,12 @@ dependencies = [
"windows-targets 0.48.5",
]
+[[package]]
+name = "percent-encoding"
+version = "2.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
+
[[package]]
name = "petgraph"
version = "0.6.4"
@@ -405,12 +789,54 @@ version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5be167a7af36ee22fe3115051bc51f6e6c7054c9348e28deb4f49bd6f705a315"
+[[package]]
+name = "pin-project"
+version = "1.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3"
+dependencies = [
+ "pin-project-internal",
+]
+
+[[package]]
+name = "pin-project-internal"
+version = "1.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.50",
+]
+
+[[package]]
+name = "pin-project-lite"
+version = "0.2.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58"
+
+[[package]]
+name = "pin-utils"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
+
[[package]]
name = "precomputed-hash"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
+[[package]]
+name = "prettyplease"
+version = "0.2.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8d3928fb5db768cb86f891ff014f0144589297e3c6a1aba6ed7cecfdace270c7"
+dependencies = [
+ "proc-macro2",
+ "syn 2.0.50",
+]
+
[[package]]
name = "proc-macro-error"
version = "1.0.4"
@@ -514,6 +940,12 @@ version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
+[[package]]
+name = "rustc-demangle"
+version = "0.1.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
+
[[package]]
name = "rustversion"
version = "1.0.14"
@@ -563,6 +995,28 @@ dependencies = [
"syn 2.0.50",
]
+[[package]]
+name = "serde_derive_internals"
+version = "0.28.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e578a843d40b4189a4d66bba51d7684f57da5bd7c304c64e14bd63efbef49509"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.50",
+]
+
+[[package]]
+name = "serde_derive_internals"
+version = "0.29.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "330f01ce65a3a5fe59a60c82f3c9a024b573b8a6e875bd233fe5f934e71d54e3"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.50",
+]
+
[[package]]
name = "serde_json"
version = "1.0.114"
@@ -574,18 +1028,59 @@ dependencies = [
"serde",
]
+[[package]]
+name = "serde_path_to_error"
+version = "0.1.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "af99884400da37c88f5e9146b7f1fd0fbcae8f6eec4e9da38b67d05486f814a6"
+dependencies = [
+ "itoa",
+ "serde",
+]
+
+[[package]]
+name = "serde_urlencoded"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd"
+dependencies = [
+ "form_urlencoded",
+ "itoa",
+ "ryu",
+ "serde",
+]
+
[[package]]
name = "siphasher"
version = "0.3.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d"
+[[package]]
+name = "slab"
+version = "0.4.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67"
+dependencies = [
+ "autocfg",
+]
+
[[package]]
name = "smallvec"
version = "1.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7"
+[[package]]
+name = "socket2"
+version = "0.5.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "05ffd9c0a93b7543e062e759284fcf5f5e3b098501104bfbdde4d404db792871"
+dependencies = [
+ "libc",
+ "windows-sys 0.52.0",
+]
+
[[package]]
name = "string_cache"
version = "0.8.7"
@@ -599,6 +1094,12 @@ dependencies = [
"precomputed-hash",
]
+[[package]]
+name = "strsim"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
+
[[package]]
name = "syn"
version = "1.0.109"
@@ -620,6 +1121,48 @@ dependencies = [
"unicode-ident",
]
+[[package]]
+name = "sync_wrapper"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160"
+
+[[package]]
+name = "sync_wrapper"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "384595c11a4e2969895cad5a8c4029115f5ab956a9e5ef4de79d11a426e5f20c"
+
+[[package]]
+name = "tapi"
+version = "0.1.0"
+dependencies = [
+ "axum",
+ "dyn-clone",
+ "futures-util",
+ "heck",
+ "indexmap",
+ "itertools 0.12.1",
+ "openapiv3",
+ "serde",
+ "serde_json",
+ "tapi-macro",
+ "tsify",
+]
+
+[[package]]
+name = "tapi-macro"
+version = "0.1.0"
+dependencies = [
+ "darling",
+ "heck",
+ "prettyplease",
+ "proc-macro2",
+ "quote",
+ "serde_derive_internals 0.29.0",
+ "syn 2.0.50",
+]
+
[[package]]
name = "term"
version = "0.7.0"
@@ -660,6 +1203,105 @@ dependencies = [
"crunchy",
]
+[[package]]
+name = "tokio"
+version = "1.37.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787"
+dependencies = [
+ "backtrace",
+ "libc",
+ "mio",
+ "pin-project-lite",
+ "socket2",
+ "tokio-macros",
+ "windows-sys 0.48.0",
+]
+
+[[package]]
+name = "tokio-macros"
+version = "2.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.50",
+]
+
+[[package]]
+name = "tower"
+version = "0.4.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c"
+dependencies = [
+ "futures-core",
+ "futures-util",
+ "pin-project",
+ "pin-project-lite",
+ "tokio",
+ "tower-layer",
+ "tower-service",
+ "tracing",
+]
+
+[[package]]
+name = "tower-layer"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0"
+
+[[package]]
+name = "tower-service"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52"
+
+[[package]]
+name = "tracing"
+version = "0.1.40"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef"
+dependencies = [
+ "log",
+ "pin-project-lite",
+ "tracing-core",
+]
+
+[[package]]
+name = "tracing-core"
+version = "0.1.32"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54"
+dependencies = [
+ "once_cell",
+]
+
+[[package]]
+name = "tsify"
+version = "0.4.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d6b26cf145f2f3b9ff84e182c448eaf05468e247f148cf3d2a7d67d78ff023a0"
+dependencies = [
+ "gloo-utils",
+ "serde",
+ "serde_json",
+ "tsify-macros",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "tsify-macros"
+version = "0.4.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7a94b0f0954b3e59bfc2c246b4c8574390d94a4ad4ad246aaf2fb07d7dfd3b47"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "serde_derive_internals 0.28.0",
+ "syn 2.0.50",
+]
+
[[package]]
name = "unicode-ident"
version = "1.0.12"
@@ -763,6 +1405,16 @@ version = "0.2.91"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4f186bd2dcf04330886ce82d6f33dd75a7bfcf69ecf5763b89fcde53b6ac9838"
+[[package]]
+name = "web-sys"
+version = "0.3.68"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "96565907687f7aceb35bc5fc03770a8a0471d82e479f25832f54a0e3f4b28446"
+dependencies = [
+ "js-sys",
+ "wasm-bindgen",
+]
+
[[package]]
name = "winapi"
version = "0.3.9"
@@ -785,6 +1437,15 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
+[[package]]
+name = "windows-sys"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
+dependencies = [
+ "windows-targets 0.48.5",
+]
+
[[package]]
name = "windows-sys"
version = "0.52.0"
diff --git a/crates/core/Cargo.toml b/crates/core/Cargo.toml
index 9642695fe..79fc780dd 100644
--- a/crates/core/Cargo.toml
+++ b/crates/core/Cargo.toml
@@ -93,6 +93,7 @@ serde = { workspace = true }
serde_json = { workspace = true }
serde_urlencoded = { workspace = true }
strum = { workspace = true }
+tapi = { workspace = true }
tantivy = { workspace = true }
thiserror = { workspace = true }
tokenizers = { workspace = true }
diff --git a/crates/core/src/api/autosuggest.rs b/crates/core/src/api/autosuggest.rs
index d6cfe6ceb..35d742fc0 100644
--- a/crates/core/src/api/autosuggest.rs
+++ b/crates/core/src/api/autosuggest.rs
@@ -14,15 +14,13 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
-use std::{collections::HashMap, sync::Arc};
-
-use axum::{extract, response::IntoResponse, Json};
+use axum::{extract, Json};
use serde::Serialize;
use utoipa::{IntoParams, ToSchema};
use crate::highlighted::HighlightedFragment;
-use super::State;
+use super::AppState;
fn highlight(query: &str, suggestion: &str) -> Vec {
let idx = suggestion
@@ -42,17 +40,17 @@ fn highlight(query: &str, suggestion: &str) -> Vec {
new_suggestion
}
-#[derive(Serialize, ToSchema)]
+#[derive(Serialize, ToSchema, tapi::Tapi)]
#[serde(rename_all = "camelCase")]
pub struct Suggestion {
highlighted: Vec,
raw: String,
}
-#[derive(Debug, serde::Serialize, serde::Deserialize, IntoParams)]
+#[derive(Debug, serde::Serialize, serde::Deserialize, IntoParams, tapi::Tapi)]
#[serde(rename_all = "camelCase")]
pub struct AutosuggestQuery {
- q: String,
+ q: Option,
}
#[utoipa::path(
@@ -63,12 +61,12 @@ pub struct AutosuggestQuery {
(status = 200, description = "Autosuggest", body = Vec),
)
)]
-
+#[tapi::tapi(path = "/autosuggest", method = Post, state = AppState)]
pub async fn route(
- extract::State(state): extract::State>,
- extract::Query(params): extract::Query>,
-) -> impl IntoResponse {
- if let Some(query) = params.get("q") {
+ extract::State(state): extract::State,
+ extract::Query(params): extract::Query,
+) -> Json> {
+ if let Some(query) = ¶ms.q {
let mut suggestions = Vec::new();
for suggestion in state.autosuggest.suggestions(query).unwrap() {
@@ -85,11 +83,12 @@ pub async fn route(
}
}
+#[tapi::tapi(path = "/autosuggest/browser", method = Post, state = AppState)]
pub async fn browser(
- extract::State(state): extract::State>,
- extract::Query(params): extract::Query>,
-) -> impl IntoResponse {
- if let Some(query) = params.get("q") {
+ extract::State(state): extract::State,
+ extract::Query(params): extract::Query,
+) -> Json<(String, Vec)> {
+ if let Some(query) = ¶ms.q {
Json((query.clone(), state.autosuggest.suggestions(query).unwrap()))
} else {
Json((String::new(), Vec::new()))
diff --git a/crates/core/src/api/explore.rs b/crates/core/src/api/explore.rs
index 979e45169..2fdc941fb 100644
--- a/crates/core/src/api/explore.rs
+++ b/crates/core/src/api/explore.rs
@@ -15,11 +15,10 @@
// along with this program. If not, see .
use axum::extract;
-use http::StatusCode;
use optics::{HostRankings, Optic};
use utoipa::ToSchema;
-#[derive(serde::Deserialize, ToSchema)]
+#[derive(serde::Deserialize, ToSchema, tapi::Tapi)]
#[serde(rename_all = "camelCase")]
pub struct ExploreExportOpticParams {
chosen_hosts: Vec,
@@ -34,12 +33,13 @@ pub struct ExploreExportOpticParams {
(status = 200, description = "Export explored sites as an optic", body = String),
)
)]
+#[tapi::tapi(path = "/expore/export", method = Post)]
pub async fn explore_export_optic(
extract::Json(ExploreExportOpticParams {
chosen_hosts,
similar_hosts,
}): extract::Json,
-) -> Result {
+) -> String {
let matches = similar_hosts
.into_iter()
.chain(chosen_hosts.clone().into_iter())
@@ -69,5 +69,5 @@ pub async fn explore_export_optic(
..Default::default()
};
- Ok(optic.to_string())
+ optic.to_string()
}
diff --git a/crates/core/src/api/hosts.rs b/crates/core/src/api/hosts.rs
index 363fd8a7c..8dd4ccad3 100644
--- a/crates/core/src/api/hosts.rs
+++ b/crates/core/src/api/hosts.rs
@@ -14,16 +14,11 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
-use axum::{
- body::Body,
- extract,
- response::{IntoResponse, Response},
-};
-use http::StatusCode;
+use axum::{extract, Json};
use optics::{HostRankings, Optic};
use utoipa::ToSchema;
-#[derive(serde::Deserialize, ToSchema)]
+#[derive(serde::Deserialize, ToSchema, tapi::Tapi)]
#[serde(rename_all = "camelCase")]
pub struct HostsExportOpticParams {
host_rankings: HostRankings,
@@ -36,13 +31,14 @@ pub struct HostsExportOpticParams {
(status = 200, description = "Export host rankings as an optic", body = String),
)
)]
+#[tapi::tapi(path = "/hosts/export", method = Post)]
pub async fn hosts_export_optic(
extract::Json(HostsExportOpticParams { host_rankings }): extract::Json,
-) -> Result, StatusCode> {
+) -> Json {
let optic = Optic {
host_rankings,
..Default::default()
};
- Ok(optic.to_string().into_response())
+ Json(optic.to_string())
}
diff --git a/crates/core/src/api/improvement.rs b/crates/core/src/api/improvement.rs
index 18851ba5c..65d3e916b 100644
--- a/crates/core/src/api/improvement.rs
+++ b/crates/core/src/api/improvement.rs
@@ -14,8 +14,6 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
-use std::sync::Arc;
-
use axum::{extract, response::IntoResponse};
use serde::Deserialize;
use url::Url;
@@ -23,7 +21,7 @@ use uuid::Uuid;
use crate::improvement::{ImprovementEvent, StoredQuery};
-use super::State;
+use super::AppState;
#[derive(Deserialize, Debug)]
pub struct ClickParams {
@@ -39,7 +37,7 @@ pub struct StoreParams {
pub async fn click(
extract::Query(params): extract::Query,
- extract::State(state): extract::State>,
+ extract::State(state): extract::State,
) {
if let Some(q) = state.improvement_queue.as_ref() {
q.lock().await.push(ImprovementEvent::Click {
@@ -62,7 +60,7 @@ impl TryFrom for StoredQuery {
}
pub async fn store(
- extract::State(state): extract::State>,
+ extract::State(state): extract::State,
extract::Json(params): extract::Json,
) -> impl IntoResponse {
match state.improvement_queue.as_ref() {
diff --git a/crates/core/src/api/mod.rs b/crates/core/src/api/mod.rs
index 0b5177c69..614e0a779 100644
--- a/crates/core/src/api/mod.rs
+++ b/crates/core/src/api/mod.rs
@@ -72,6 +72,7 @@ pub struct Counters {
pub daily_active_users: user_count::UserCount,
}
+pub type AppState = Arc;
pub struct State {
pub config: ApiConfig,
pub searcher: ApiSearcher,
@@ -222,6 +223,32 @@ pub async fn router(config: &ApiConfig, counters: Counters) -> Result {
Ok(build_router(state))
}
+pub fn endpoints() -> tapi::endpoints::Endpoints<'static, AppState> {
+ type E = &'static dyn tapi::endpoints::Endpoint;
+
+ tapi::endpoints::Endpoints::new([
+ &autosuggest::browser::endpoint as E,
+ &autosuggest::route::endpoint as E,
+ &explore::explore_export_optic::endpoint as E,
+ // &favicon::endpoint as E,
+ &hosts::hosts_export_optic::endpoint as E,
+ // &improvement::click::endpoint as E,
+ // &improvement::store::endpoint as E,
+ // &search::entity_image::endpoint as E,
+ &search::search::endpoint as E,
+ &search::sidebar::endpoint as E,
+ &search::spellcheck::endpoint as E,
+ &search::widget::endpoint as E,
+ // &summarize::summarize_route::endpoint as E,
+ &webgraph::host::ingoing_hosts::endpoint as E,
+ &webgraph::host::knows::endpoint as E,
+ &webgraph::host::outgoing_hosts::endpoint as E,
+ &webgraph::host::similar::endpoint as E,
+ &webgraph::page::ingoing_pages::endpoint as E,
+ &webgraph::page::outgoing_pages::endpoint as E,
+ ])
+}
+
/// Enables CORS for development where the API and frontend are on
/// different hosts.
fn cors_layer() -> tower_http::cors::CorsLayer {
@@ -238,7 +265,7 @@ pub fn metrics_router(registry: crate::metrics::PrometheusRegistry) -> Router {
}
async fn search_metric(
- extract::State(state): extract::State>,
+ extract::State(state): extract::State,
extract::ConnectInfo(addr): extract::ConnectInfo,
request: axum::extract::Request,
next: middleware::Next,
diff --git a/crates/core/src/api/search.rs b/crates/core/src/api/search.rs
index 94bf3c20d..fa17f1db4 100644
--- a/crates/core/src/api/search.rs
+++ b/crates/core/src/api/search.rs
@@ -17,7 +17,6 @@
use crate::config::defaults;
use http::StatusCode;
use optics::{HostRankings, Optic};
-use std::sync::Arc;
use utoipa::ToSchema;
use axum::Json;
@@ -29,11 +28,11 @@ use crate::{
webpage::region::Region,
};
-use super::State;
+use super::AppState;
use axum::{extract, response::IntoResponse};
-#[derive(Debug, serde::Serialize, serde::Deserialize, ToSchema)]
+#[derive(Debug, serde::Serialize, serde::Deserialize, ToSchema, tapi::Tapi)]
#[serde(rename_all = "camelCase")]
#[schema(title = "SearchQuery", example = json!({"query": "hello world"}))]
pub struct ApiSearchQuery {
@@ -81,7 +80,7 @@ impl TryFrom for SearchQuery {
}
}
-#[derive(Debug, serde::Serialize, serde::Deserialize, ToSchema)]
+#[derive(Debug, serde::Serialize, serde::Deserialize, ToSchema, tapi::Tapi)]
#[serde(tag = "type", rename_all = "camelCase")]
pub enum ApiSearchResult {
Websites(WebsitesResult),
@@ -106,17 +105,24 @@ impl From for ApiSearchResult {
(status = 200, description = "Search results", body = ApiSearchResult),
)
)]
+#[tapi::tapi(path = "/search", method = Post, state = AppState)]
pub async fn search(
- extract::State(state): extract::State>,
+ extract::State(state): extract::State,
extract::Json(query): extract::Json,
-) -> Result {
+) -> tapi::endpoints::OneOf5<
+ extract::Json,
+ extract::Json,
+ String,
+ tapi::endpoints::Statused<400, ()>,
+ tapi::endpoints::Statused<500, ()>,
+> {
tracing::debug!(?query);
let flatten_result = query.flatten_response;
let query = SearchQuery::try_from(query);
if let Err(err) = query {
tracing::error!("{:?}", err);
- return Err(StatusCode::BAD_REQUEST);
+ return tapi::endpoints::OneOf5::D(().into());
}
let mut query = query.unwrap();
@@ -125,27 +131,25 @@ pub async fn search(
match state.searcher.search(&query).await {
Ok(result) => {
if flatten_result {
- Ok(Json(ApiSearchResult::from(result)).into_response())
+ tapi::endpoints::OneOf5::A(Json(ApiSearchResult::from(result)))
} else {
- Ok(Json(result).into_response())
+ tapi::endpoints::OneOf5::B(Json(result))
}
}
Err(err) => match err.downcast_ref() {
Some(searcher::distributed::Error::EmptyQuery) => {
- Ok(searcher::distributed::Error::EmptyQuery
- .to_string()
- .into_response())
+ tapi::endpoints::OneOf5::C(searcher::distributed::Error::EmptyQuery.to_string())
}
_ => {
tracing::error!("{:?}", err);
- Err(StatusCode::INTERNAL_SERVER_ERROR)
+ tapi::endpoints::OneOf5::E(().into())
}
},
}
}
-#[derive(Debug, serde::Serialize, serde::Deserialize, ToSchema)]
+#[derive(Debug, serde::Serialize, serde::Deserialize, ToSchema, tapi::Tapi)]
pub struct WidgetQuery {
pub query: String,
}
@@ -159,14 +163,15 @@ pub struct WidgetQuery {
(status = 200, description = "The resulting widget if one matches the query", body = Option),
)
)]
+#[tapi::tapi(path = "/search/widget", method = Post, state = AppState)]
pub async fn widget(
- extract::State(state): extract::State>,
+ extract::State(state): extract::State,
extract::Json(req): extract::Json,
-) -> impl IntoResponse {
+) -> extract::Json