feat(api): declare typed WebSocket operations

This commit is contained in:
2026-09-23 21:07:20 +09:00
parent ed99be3e24
commit 9c107eaf74
39 changed files with 1144 additions and 67 deletions
@@ -0,0 +1,17 @@
use api_macros::api;
pub struct Frame;
#[api]
pub trait DuplicateWebSocketPathParameterApi {
#[websocket(
"/widgets/{widget_id}/events",
method = GET,
client_to_server = Frame,
server_to_client = Frame,
path_parameters = [widget_id: u64, widget_id: String]
)]
type Events;
}
fn main() {}
@@ -0,0 +1,5 @@
error: duplicate path parameter `widget_id`
--> tests/ui/duplicate_websocket_path_parameter.rs:12:44
|
12 | path_parameters = [widget_id: u64, widget_id: String]
| ^^^^^^^^^
@@ -0,0 +1,21 @@
use api_macros::api;
pub struct Frame;
pub struct Response;
#[api]
pub trait DuplicateTransportRouteApi {
#[get("/widgets/{widget_id}/events")]
async fn events(&self, #[path] widget_id: u64) -> Response;
#[websocket(
"/widgets/{widget_id}/events",
method = GET,
client_to_server = Frame,
server_to_client = Frame,
path_parameters = [widget_id: u64]
)]
type WidgetEvents;
}
fn main() {}
@@ -0,0 +1,5 @@
error: duplicate route for GET `/widgets/{widget_id}/events`
--> tests/ui/duplicate_websocket_route.rs:18:10
|
18 | type WidgetEvents;
| ^^^^^^^^^^^^
@@ -0,0 +1,18 @@
use api_macros::api;
pub struct Frame;
#[api]
pub trait InvalidWebSocketAlternateStatusApi {
#[websocket(
"/events",
method = GET,
client_to_server = Frame,
server_to_client = Frame,
path_parameters = [],
alternate_status = 204
)]
type Events;
}
fn main() {}
@@ -0,0 +1,5 @@
error: WebSocket operations cannot declare unary success responses or statuses
--> tests/ui/invalid_websocket_alternate_status.rs:13:9
|
13 | alternate_status = 204
| ^^^^^^^^^^^^^^^^
@@ -0,0 +1,19 @@
use api_macros::api;
pub struct Frame;
pub struct Body;
#[api]
pub trait InvalidWebSocketBinaryBodyApi {
#[websocket(
"/events",
method = GET,
client_to_server = Frame,
server_to_client = Frame,
path_parameters = [],
binary = Body
)]
type Events;
}
fn main() {}
@@ -0,0 +1,5 @@
error: WebSocket operations cannot declare JSON or binary request bodies
--> tests/ui/invalid_websocket_binary_body.rs:14:9
|
14 | binary = Body
| ^^^^^^
@@ -0,0 +1,19 @@
use api_macros::api;
pub struct Frame;
pub struct Body;
#[api]
pub trait InvalidWebSocketBodyApi {
#[websocket(
"/events",
method = GET,
client_to_server = Frame,
server_to_client = Frame,
path_parameters = [],
body = Body
)]
type Events;
}
fn main() {}
@@ -0,0 +1,5 @@
error: WebSocket operations cannot declare JSON or binary request bodies
--> tests/ui/invalid_websocket_body.rs:14:9
|
14 | body = Body
| ^^^^
@@ -0,0 +1,17 @@
use api_macros::api;
pub struct Frame;
#[api]
pub trait InvalidWebSocketFrameApi {
#[websocket(
"/events",
method = GET,
client_to_server = (Frame, Frame),
server_to_client = Frame,
path_parameters = []
)]
type Events;
}
fn main() {}
@@ -0,0 +1,5 @@
error: WebSocket frame authorities must use direct named Rust types
--> tests/ui/invalid_websocket_frame.rs:10:28
|
10 | client_to_server = (Frame, Frame),
| ^^^^^^^^^^^^^^
@@ -0,0 +1,17 @@
use api_macros::api;
pub struct Frame;
#[api]
pub trait InvalidWebSocketMethodApi {
#[websocket(
"/events",
method = POST,
client_to_server = Frame,
server_to_client = Frame,
path_parameters = []
)]
type Events;
}
fn main() {}
@@ -0,0 +1,5 @@
error: WebSocket operations require `method = GET`
--> tests/ui/invalid_websocket_method.rs:9:18
|
9 | method = POST,
| ^^^^
@@ -0,0 +1,18 @@
use api_macros::api;
pub struct Frame;
#[api]
pub trait InvalidWebSocketResponseApi {
#[websocket(
"/events",
method = GET,
client_to_server = Frame,
server_to_client = Frame,
path_parameters = [],
status = 101
)]
type Events;
}
fn main() {}
@@ -0,0 +1,5 @@
error: WebSocket operations cannot declare unary success responses or statuses
--> tests/ui/invalid_websocket_response.rs:13:9
|
13 | status = 101
| ^^^^^^
@@ -0,0 +1,19 @@
use api_macros::api;
pub struct Frame;
pub struct Response;
#[api]
pub trait InvalidWebSocketResponseBodyApi {
#[websocket(
"/events",
method = GET,
client_to_server = Frame,
server_to_client = Frame,
path_parameters = [],
response = Response
)]
type Events;
}
fn main() {}
@@ -0,0 +1,5 @@
error: WebSocket operations cannot declare unary success responses or statuses
--> tests/ui/invalid_websocket_response_body.rs:14:9
|
14 | response = Response
| ^^^^^^^^
@@ -0,0 +1,16 @@
use api_macros::api;
pub struct Frame;
#[api]
pub trait MissingWebSocketFrameApi {
#[websocket(
"/events",
method = GET,
client_to_server = Frame,
path_parameters = []
)]
type Events;
}
fn main() {}
@@ -0,0 +1,5 @@
error: WebSocket operations require `server_to_client = FrameType`
--> tests/ui/missing_websocket_frame.rs:8:9
|
8 | "/events",
| ^^^^^^^^^
@@ -0,0 +1,17 @@
use api_macros::api;
pub struct Frame;
#[api]
pub trait InvalidWebSocketPathApi {
#[websocket(
"/widgets/{widget_id}/events",
method = GET,
client_to_server = Frame,
server_to_client = Frame,
path_parameters = [other_id: u64]
)]
type Events;
}
fn main() {}
@@ -0,0 +1,5 @@
error: path placeholder(s) have no matching path parameter: widget_id
--> tests/ui/websocket_path_mismatch.rs:8:9
|
8 | "/widgets/{widget_id}/events",
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -0,0 +1,17 @@
use api_macros::api;
pub struct Frame;
#[api]
pub trait UnusedWebSocketPathParameterApi {
#[websocket(
"/events",
method = GET,
client_to_server = Frame,
server_to_client = Frame,
path_parameters = [unused: u64]
)]
type Events;
}
fn main() {}
@@ -0,0 +1,5 @@
error: path parameter(s) have no matching placeholder: unused
--> tests/ui/websocket_unused_path_parameter.rs:8:9
|
8 | "/events",
| ^^^^^^^^^