Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
23 changes: 19 additions & 4 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,25 @@ jobs:
steps:
- uses: actions/checkout@v4
- uses: biomejs/setup-biome@v2
- uses: dtolnay/rust-toolchain@stable
- uses: dtolnay/rust-toolchain@1.78.0
with:
components: rustfmt
components: rustfmt, clippy
- uses: Swatinem/rust-cache@v2
- run: cargo fmt -- --check
- run: cargo clippy --all-targets -- -D warnings
- run: cargo test
- run: SQLX_OFFLINE=true cargo clippy --all-targets --all-features -- -D warnings
- run: SQLX_OFFLINE=true cargo test --workspace

typescript:
name: TypeScript test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
cache-dependency-path: 'reflectapi-demo/clients/typescript/package-lock.json'
- run: npm ci
working-directory: reflectapi-demo/clients/typescript
- run: npm test
working-directory: reflectapi-demo/clients/typescript
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@

ReflectAPI is a library for Rust code-first web service API declaration and corresponding clients code generation tools.

## Features

- **Code-First API Design**: Define your API in Rust using traits and generate clients automatically
- **Transport Metadata**: Rich access to HTTP status codes, headers, timing, and raw transport objects
- **Multi-Language Support**: Generate TypeScript and Rust clients from the same API definition
- **Error Handling**: Comprehensive error types with transport metadata for advanced error handling
- **Backward Compatible**: Existing code continues to work while new features are opt-in

More documentation will follow later.

### Development notes
Expand Down
4 changes: 2 additions & 2 deletions reflectapi-cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ enum Commands {
#[arg(long, value_delimiter = ',')]
shared_modules: Option<Vec<String>>,

#[arg(short, long, value_delimiter = ',')]
#[arg(short = 'i', long, value_delimiter = ',')]
include_tags: Vec<String>,

#[arg(short, long, value_delimiter = ',')]
Expand All @@ -54,7 +54,7 @@ enum Commands {
format: bool,

/// Instrument the generated code with tracing
#[arg(short, long, default_value = "false")]
#[arg(short = 'n', long, default_value = "false")]
instrument: bool,
},
/// Documentation subcommands
Expand Down
3 changes: 2 additions & 1 deletion reflectapi-demo/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ reflectapi = { workspace = true, features = [
"codegen",
"msgpack",
"json",
"indexmap"
"indexmap",
"rt"
] }

tokio = { version = "1.5.0", features = ["full"] }
Expand Down
19 changes: 12 additions & 7 deletions reflectapi-demo/clients/rust/generated/src/generated.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,10 @@ pub mod interface {
&self,
input: reflectapi::Empty,
headers: reflectapi::Empty,
) -> Result<reflectapi::Empty, reflectapi::rt::Error<reflectapi::Empty, C::Error>> {
) -> Result<
reflectapi::rt::ApiResult<reflectapi::Empty>,
reflectapi::rt::Error<reflectapi::Empty, C::Error>,
> {
reflectapi::rt::__request_impl(
&self.client,
self.base_url
Expand Down Expand Up @@ -98,7 +101,9 @@ pub mod interface {
input: super::types::myapi::proto::PetsListRequest,
headers: super::types::myapi::proto::Headers,
) -> Result<
super::types::myapi::proto::Paginated<super::types::myapi::model::output::Pet>,
reflectapi::rt::ApiResult<
super::types::myapi::proto::Paginated<super::types::myapi::model::output::Pet>,
>,
reflectapi::rt::Error<super::types::myapi::proto::PetsListError, C::Error>,
> {
reflectapi::rt::__request_impl(
Expand All @@ -118,7 +123,7 @@ pub mod interface {
input: super::types::myapi::proto::PetsCreateRequest,
headers: super::types::myapi::proto::Headers,
) -> Result<
reflectapi::Empty,
reflectapi::rt::ApiResult<reflectapi::Empty>,
reflectapi::rt::Error<super::types::myapi::proto::PetsCreateError, C::Error>,
> {
reflectapi::rt::__request_impl(
Expand All @@ -138,7 +143,7 @@ pub mod interface {
input: super::types::myapi::proto::PetsUpdateRequest,
headers: super::types::myapi::proto::Headers,
) -> Result<
reflectapi::Empty,
reflectapi::rt::ApiResult<reflectapi::Empty>,
reflectapi::rt::Error<super::types::myapi::proto::PetsUpdateError, C::Error>,
> {
reflectapi::rt::__request_impl(
Expand All @@ -158,7 +163,7 @@ pub mod interface {
input: super::types::myapi::proto::PetsRemoveRequest,
headers: super::types::myapi::proto::Headers,
) -> Result<
reflectapi::Empty,
reflectapi::rt::ApiResult<reflectapi::Empty>,
reflectapi::rt::Error<super::types::myapi::proto::PetsRemoveError, C::Error>,
> {
reflectapi::rt::__request_impl(
Expand All @@ -179,7 +184,7 @@ pub mod interface {
input: super::types::myapi::proto::PetsRemoveRequest,
headers: super::types::myapi::proto::Headers,
) -> Result<
reflectapi::Empty,
reflectapi::rt::ApiResult<reflectapi::Empty>,
reflectapi::rt::Error<super::types::myapi::proto::PetsRemoveError, C::Error>,
> {
reflectapi::rt::__request_impl(
Expand All @@ -199,7 +204,7 @@ pub mod interface {
input: reflectapi::Empty,
headers: super::types::myapi::proto::Headers,
) -> Result<
std::option::Option<super::types::myapi::model::output::Pet>,
reflectapi::rt::ApiResult<std::option::Option<super::types::myapi::model::output::Pet>>,
reflectapi::rt::Error<super::types::myapi::proto::UnauthorizedError, C::Error>,
> {
reflectapi::rt::__request_impl(
Expand Down
10 changes: 5 additions & 5 deletions reflectapi-demo/clients/rust/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,19 @@ async fn main() {
.await;
// error handling demo:
match result {
Ok(_v) => {
Ok(_) => {
// use structured application response data here
println!("Health check successful")
}
Err(e) => match e {
Error::Application(_v) => {
Error::Application { error: _v, .. } => {
// use structured application error here
println!("Health check failed")
}
Error::Network(e) => {
Error::Network { error: e, .. } => {
println!("Network error: {:?}", e)
}
Error::Protocol { info, stage } => match stage {
Error::Protocol { info, stage, .. } => match stage {
ProtocolErrorStage::SerializeRequestBody => {
eprint!("Failed to serialize request body: {}", info)
}
Expand All @@ -43,7 +43,7 @@ async fn main() {
)
}
},
Error::Server(status, body) => {
Error::Server { status, body, .. } => {
println!("Server error: {} with body: {:?}", status, body)
}
},
Expand Down
Loading
Loading