Skip to content

Commit 82471a3

Browse files
committed
Split lib
1 parent 3bbde31 commit 82471a3

File tree

13 files changed

+377
-283
lines changed

13 files changed

+377
-283
lines changed

AGENTS.md

Lines changed: 70 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,36 @@
11
# VESPERA PROJECT KNOWLEDGE BASE
22

3-
**Generated:** 2026-03-19
3+
**Generated:** 2026-03-21
44
**Branch:** main
55

66
## OVERVIEW
77

88
Vespera is a fully automated OpenAPI 3.1 engine for Axum - delivers FastAPI-like DX to Rust. Zero-config route discovery via compile-time macro scanning.
99

10-
Also provides in-process dispatch (`inprocess` feature) and JNI integration (`jni` feature) for embedding Rust axum apps inside Java/Spring applications without HTTP overhead.
10+
Also provides in-process dispatch (`vespera_inprocess` crate) and JNI integration (`vespera_jni` crate) for embedding Rust axum apps inside Java/Spring applications without HTTP overhead.
1111

1212
## STRUCTURE
1313

1414
```
1515
vespera/
1616
├── crates/
1717
│ ├── vespera/ # Public API - re-exports everything
18-
│ │ ├── src/lib.rs # Core re-exports + conditional modules
19-
│ │ ├── src/inprocess.rs # In-process dispatch (feature: inprocess)
20-
│ │ └── src/jni.rs # JNI integration (feature: jni)
18+
│ │ └── src/lib.rs # Core re-exports (no transport deps)
2119
│ ├── vespera_core/ # OpenAPI types, route/schema abstractions
22-
│ └── vespera_macro/ # Proc-macros (main logic lives here)
20+
│ ├── vespera_macro/ # Proc-macros (main logic lives here)
21+
│ ├── vespera_inprocess/ # In-process dispatch (transport-agnostic)
22+
│ │ └── src/lib.rs # dispatch(), register_app(), dispatch_from_json()
23+
│ └── vespera_jni/ # JNI bridge (depends on vespera_inprocess)
24+
│ └── src/lib.rs # RUNTIME, jni_app! macro, JNI symbol export
2325
├── libs/
2426
│ └── vespera-bridge/ # Java library (com.devfive.vespera.bridge)
2527
│ ├── VesperaBridge.java # JNI native loader + dispatch
2628
│ └── VesperaProxyController.java # Auto-configured Spring proxy
2729
├── examples/
2830
│ ├── axum-example/ # Standard axum server demo
2931
│ └── rust-jni-demo/ # JNI + standalone server demo
30-
│ ├── src/ # Rust: routes, create_app(), JNI_OnLoad
31-
│ └── java/demo-app/ # Java: Spring Boot proxy (16 lines)
32+
│ ├── src/ # Rust: routes, create_app(), jni_app!
33+
│ └── java/demo-app/ # Java: Spring Boot proxy
3234
```
3335

3436
## WHERE TO LOOK
@@ -43,8 +45,9 @@ vespera/
4345
| Modify schema_type! macro | `crates/vespera_macro/src/schema_macro.rs` | Type derivation & SeaORM support |
4446
| Add core types | `crates/vespera_core/src/` | OpenAPI spec types |
4547
| Test new features | `examples/axum-example/` | Add route, run example |
46-
| In-process dispatch | `crates/vespera/src/inprocess.rs` | RequestEnvelope → Router → ResponseEnvelope |
47-
| JNI integration | `crates/vespera/src/jni.rs` | JNI_OnLoad macro, fixed JNI symbol export |
48+
| In-process dispatch | `crates/vespera_inprocess/src/lib.rs` | RequestEnvelope → Router → ResponseEnvelope |
49+
| App factory (FFI pattern) | `crates/vespera_inprocess/src/lib.rs` | register_app(), dispatch_from_json() |
50+
| JNI integration | `crates/vespera_jni/src/lib.rs` | RUNTIME, jni_app! macro, JNI symbol export |
4851
| Java bridge library | `libs/vespera-bridge/` | com.devfive.vespera.bridge package |
4952
| JNI demo (Rust) | `examples/rust-jni-demo/src/` | Routes + vespera::jni_app! |
5053
| JNI demo (Java) | `examples/rust-jni-demo/java/` | Spring Boot proxy app |
@@ -59,30 +62,69 @@ vespera/
5962
| `vespera_macro/src/parser/parameters.rs` | ~845 | Extract path/query params from handlers |
6063
| `vespera_macro/src/openapi_generator.rs` | ~808 | OpenAPI doc assembly |
6164
| `vespera_macro/src/collector.rs` | ~707 | Filesystem route scanning |
62-
| `vespera/src/inprocess.rs` | ~150 | In-process HTTP dispatch via oneshot |
63-
| `vespera/src/jni.rs` | ~155 | JNI exports + `jni_app!` macro |
65+
| `vespera_inprocess/src/lib.rs` | ~175 | In-process dispatch + app factory |
66+
| `vespera_jni/src/lib.rs` | ~95 | JNI RUNTIME + jni_app! macro + JNI symbol |
6467

65-
## FEATURES (crates/vespera)
68+
## CRATE DEPENDENCY GRAPH
69+
70+
```
71+
vespera (OpenAPI framework)
72+
├── vespera_core
73+
├── vespera_macro
74+
├── vespera_inprocess (optional, feature = "inprocess")
75+
└── vespera_jni (optional, feature = "jni", implies "inprocess")
76+
77+
vespera_inprocess (transport layer — no JNI deps)
78+
├── axum (direct — owns Router re-export)
79+
├── http, http-body-util, tower
80+
├── serde, serde_json
81+
└── tokio (rt only — for dispatch_from_json Runtime param)
82+
83+
vespera_jni (JNI glue — thin layer)
84+
├── vespera_inprocess (via workspace)
85+
├── jni
86+
└── tokio (rt-multi-thread — for LazyLock<Runtime>)
87+
88+
rust-jni-demo (example — depends on vespera ONLY)
89+
└── vespera = { features = ["jni"] }
90+
```
91+
92+
## USER-FACING API
93+
94+
Users depend on `vespera` only. Internal crates are never depended on directly.
6695

6796
```toml
68-
[features]
69-
default = [...] # axum-extra features
70-
inprocess = [http, http-body-util, tower, serde] # In-process dispatch
71-
jni = [inprocess, jni-crate, tokio] # JNI = inprocess + JVM glue
97+
# Cargo.toml — the only dependency needed
98+
[dependencies]
99+
vespera = { version = "...", features = ["jni"] }
100+
```
101+
102+
```rust
103+
// lib.rs — all imports come from vespera
104+
use vespera::{axum, vespera};
105+
106+
pub fn create_app() -> axum::Router {
107+
vespera!(title = "My API", version = "1.0.0")
108+
}
109+
110+
vespera::jni_app!(create_app);
72111
```
73112

74-
- `inprocess`: Transport-agnostic `dispatch(Router, &RequestEnvelope) -> String`
75-
- `jni`: Adds `jni_app!` macro + `JNI_OnLoad` + fixed JNI symbol export
76-
- JNI symbol: `Java_com_devfive_vespera_bridge_VesperaBridge_dispatch`
113+
Feature flags:
114+
115+
| Feature | Re-exports | Adds |
116+
|---------|-----------|------|
117+
| `inprocess` | `vespera::inprocess` (= `vespera_inprocess`) | dispatch, register_app, envelopes |
118+
| `jni` | `vespera::jni` (= `vespera_jni`) + implies `inprocess` | RUNTIME, jni_app!, JNI symbol |
77119

78120
## JNI ARCHITECTURE
79121

80122
```
81-
Java (Spring Boot) Rust (cdylib) vespera framework
123+
Java (Spring Boot) Rust (cdylib) vespera crates
82124
───────────────── ────────────── ─────────────────
83-
VesperaBridge.init() → JNI_OnLoad register_app(create_app)
125+
VesperaBridge.init() → JNI_OnLoad vespera_inprocess::register_app()
84126
↓ ↓
85-
VesperaBridge.dispatch() → JNI symbol → inprocess::dispatch()
127+
VesperaBridge.dispatch() → JNI symbol vespera_inprocess::dispatch_from_json()
86128
↓ ↓ ↓
87129
VesperaProxyController catch_unwind router.oneshot(request)
88130
↓ ↓ ↓
@@ -131,6 +173,8 @@ Generate request/response types from existing structs with powerful transformati
131173
- **Workspace dependencies**: Internal crates use `{ workspace = true }`
132174
- **Test frameworks**: `rstest` for unit tests, `insta` for snapshots
133175
- **No `build.rs`**: All code gen via proc-macros at compile time
176+
- **No direct axum dep in examples**: Use `vespera::axum` re-export
177+
- **No direct vespera_jni/vespera_inprocess dep**: Use `vespera` features
134178
- **Java package**: `com.devfive.vespera.bridge` (fixed for JNI symbol stability)
135179
- **Java build**: Gradle (Kotlin DSL), published to GitHub Packages
136180

@@ -141,6 +185,9 @@ Generate request/response types from existing structs with powerful transformati
141185
- **NEVER** write OpenAPI JSON by hand - generated from code
142186
- **NEVER** write JNI boilerplate in examples - use `vespera::jni_app!` macro
143187
- **NEVER** parse domain JSON in Java - Spring is a proxy, Rust owns business logic
188+
- **NEVER** depend on axum directly in examples - use `vespera::axum`
189+
- **NEVER** depend on `vespera_jni` or `vespera_inprocess` directly - use `vespera` features
190+
- **NEVER** put transport logic in vespera core - use `vespera_inprocess` / `vespera_jni`
144191
- Route functions **MUST** be `pub async fn`
145192

146193
## COMMANDS

Cargo.lock

Lines changed: 25 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ readme = "README.md"
1313
[workspace.dependencies]
1414
vespera_core = { path = "crates/vespera_core", version = "0.1.44" }
1515
vespera_macro = { path = "crates/vespera_macro", version = "0.1.44" }
16+
vespera_inprocess = { path = "crates/vespera_inprocess", version = "0.1.44" }
17+
vespera_jni = { path = "crates/vespera_jni", version = "0.1.44" }
1618

1719
[workspace.lints.clippy]
1820
all = { level = "warn", priority = -1 }

crates/vespera/Cargo.toml

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ repository.workspace = true
99
[features]
1010
default = ["axum-extra/typed-header", "axum-extra/form", "axum-extra/query", "axum-extra/multipart", "axum-extra/cookie"]
1111
cron = ["dep:tokio-cron-scheduler", "dep:tokio"]
12-
inprocess = ["dep:http", "dep:http-body-util", "dep:tower", "dep:serde"]
13-
jni = ["inprocess", "dep:jni", "dep:tokio"]
12+
inprocess = ["dep:vespera_inprocess"]
13+
jni = ["inprocess", "dep:vespera_jni"]
1414

1515
[dependencies]
1616
vespera_core = { workspace = true }
@@ -23,14 +23,9 @@ serde_json = "1"
2323
tower-layer = "0.3"
2424
tower-service = "0.3"
2525
tokio-cron-scheduler = { version = "0.13", optional = true }
26-
tokio = { version = "1", features = ["rt-multi-thread"], optional = true }
27-
# inprocess feature
28-
http = { version = "1", optional = true }
29-
http-body-util = { version = "0.1", optional = true }
30-
tower = { version = "0.5", features = ["util"], optional = true }
31-
serde = { version = "1", features = ["derive"], optional = true }
32-
# jni feature
33-
jni = { version = "0.21", optional = true }
26+
tokio = { version = "1", features = ["rt"], optional = true }
27+
vespera_inprocess = { workspace = true, optional = true }
28+
vespera_jni = { workspace = true, optional = true }
3429

3530
[lints]
3631
workspace = true

0 commit comments

Comments
 (0)