Skip to content

Commit df59a0f

Browse files
committed
Update interfaces to reflect OpenAPI 3.2.0 compliance ; [README.md] Update to reflect new features from OpenAPI 3.2.0 compliance rounds
1 parent fc8f75a commit df59a0f

File tree

15 files changed

+861
-149
lines changed

15 files changed

+861
-149
lines changed

README.md

Lines changed: 112 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,51 @@
11
cdd-rust: OpenAPI ↔ Rust
22
========================
3-
[![Rust: nightly](https://img.shields.io/badge/Rust-nightly-blue.svg)](https://www.rust-lang.org)
4-
[![License: (Apache-2.0 OR MIT)](https://img.shields.io/badge/LICENSE-Apache--2.0%20OR%20MIT-orange)](LICENSE-APACHE)
5-
[![CI](https://github.com/offscale/cdd-rust/actions/workflows/ci-cargo.yml/badge.svg)](https://github.com/offscale/cdd-rust/actions/workflows/ci-cargo.yml)
3+
[![Rust: nightly](https://img.shields.io/badge/Rust-nightly-blue.svg)](https://www.rust-lang.org)
4+
[![License: (Apache-2.0 OR MIT)](https://img.shields.io/badge/LICENSE-Apache--2.0%20OR%20MIT-orange)](LICENSE-APACHE)
5+
[![CI](https://github.com/offscale/cdd-rust/actions/workflows/ci-cargo.yml/badge.svg)](https://github.com/offscale/cdd-rust/actions/workflows/ci-cargo.yml)
66

7-
**Compiler Driven Development (CDD)** for Rust.
7+
**cdd-rust** is a compiler-driven development toolchain designed to enable "Surgical" Compiler-Driven Development.
88

9-
**cdd-rust** creates a symbiotic link between your **Database**, **Rust Code**, and **OpenAPI Specifications**. Unlike traditional generators that overwrite files or hide code in "generated" directories, `cdd-rust` uses advanced AST parsing (`ra_ap_syntax`) to surgically patch your *existing* source files, strictly typed handlers, and integration tests.
9+
Unlike traditional generators that blindly overwrite files or dump code into "generated" folders, `cdd-rust` understands
10+
the Abstract Syntax Tree (AST) of your Rust code. It uses `ra_ap_syntax` (the underlying parser of **rust-analyzer**) to
11+
read, understand, and safely patch your existing source code to match your OpenAPI specifications (and vice-versa).
1012

11-
Uniquely, `cdd-rust` is built on a **strategy-based architecture**. While the default implementation provides a robust **Actix Web + Diesel** workflow, the core logic is decoupled into strategies and mappers, making it extensible to other ecosystems (e.g., Axum, SQLx) in the future.
13+
## ⚡️ Key Capabilities
1214

13-
It supports two distinct workflows:
14-
1. **Scaffold | Patch (OpenAPI ➔ Rust):** Generate/update handlers, routes, and models via `BackendStrategy`.
15-
2. **Reflect & Sync (Rust ➔ OpenAPI):** Generate OpenAPI specifications from your source code and DB via `ModelMapper`.
15+
### 1. Surgical Merging (OpenAPI ➔ Existing Rust)
16+
17+
The core engine features a non-destructive patcher (`cdd-core/patcher`) capable of merging OpenAPI definitions into an
18+
existing codebase.
19+
20+
* **AST-Aware:** It preserves your comments, whitespace, and manual formatting.
21+
* **Smart Routing:** It can parse your existing `actix_web` configuration functions and inject missing `.service()`
22+
calls without duplicating existing ones.
23+
* **Type Safety:** OpenAPI types are strictly mapped to Rust constraints:
24+
* `format: uuid``uuid::Uuid`
25+
* `format: date-time``chrono::DateTime<Utc>`
26+
* `format: password``Secret<String>`
27+
28+
### 2. Synchronization (Database ➔ Rust ➔ OpenAPI)
29+
30+
Keep your code as the single source of truth. The `sync` workflow ensures your Rust models match your Postgres database
31+
and are ready for OpenAPI generation.
32+
33+
* **DB Inspection:** Uses `dsync` to generate strictly typed Diesel structs from the DB schema.
34+
* **Attribute Injection:** Automatically parses generated structs to inject
35+
`#[derive(ToSchema, Serialize, Deserialize)]` and necessary imports, ensuring compatibility
36+
with [utoipa](https://github.com/juhaku/utoipa).
37+
38+
### 3. Contract Verification (OpenAPI ➔ Tests)
39+
40+
Generate strictly typed integration tests (`tests/api_contracts.rs`) that treat your application as a black box to
41+
verify compliance with the spec.
42+
43+
* **Smart Mocking:** Automatically creates dummy values for Path, Query, and Body parameters based on strict type
44+
definitions.
45+
* **Runtime Expression Resolution:** fully supports OAS 3.2 runtime expressions (e.g., `{$request.body#/id}`) for
46+
HATEOAS link validation.
47+
* **Schema Validation:** Verifies that API responses strictly match the JSON Schema defined in your OpenAPI document
48+
using `jsonschema`.
1649

1750
## ⚡️ The CDD Loop
1851

@@ -66,7 +99,8 @@ graph TD
6699

67100
## 🏗 Architecture
68101

69-
The internal architecture separates the core AST/OpenAPI parsing logic from the target code generation. This allows the tool to support multiple web frameworks and ORMs through the `BackendStrategy` and `ModelMapper` traits.
102+
The internal architecture separates the core AST/OpenAPI parsing logic from the target code generation. This allows the
103+
tool to support multiple web frameworks and ORMs through the `BackendStrategy` and `ModelMapper` traits.
70104

71105
```mermaid
72106
graph LR
@@ -126,82 +160,97 @@ graph LR
126160
class T_Future future
127161
```
128162

129-
---
163+
The project is workspace-based to separate core logic from the command-line interface.
130164

131-
## 🚀 Features
132-
133-
### 1. Framework-Agnostic Scaffolding (OpenAPI ➔ Rust)
134-
Stop manually writing repetitive handler signatures. `cdd-rust` reads your spec and generates strictly typed code based on the active `BackendStrategy`.
135-
* **Handler Scaffolding:** Transforms OpenAPI paths into `async fn` signatures with correct extractors (currently `ActixStrategy` defaults):
136-
* Path variables ➔ `web::Path<Uuid>`
137-
* Query strings ➔ `web::Query<Value>`
138-
* Request bodies ➔ `web::Json<T>`
139-
* **Route Registration:** Surgically injects route configuration strings (e.g., `cfg.service(...)`) using AST analysis, preserving existing logic.
140-
* **Non-Destructive Patching:** Uses [`ra_ap_syntax`](https://docs.rs/ra_ap_syntax/) (official [rust-analyzer](https://github.com/rust-lang/rust-analyzer) parser) to edit files safely.
141-
142-
### 2. Source-of-Truth Reflection (Rust ➔ OpenAPI)
143-
Keep your documentation alive. Your Rust code *is* the spec.
144-
* **Model Mapper Trait:** Extracts DB Schemas via `ModelMapper` (currently `DieselMapper` wrapping `dsync`) to generate/update Rust structs.
145-
* **Attribute Injection:** Automatically parses structs and injects `#[derive(ToSchema)]` and `#[serde(...)]` attributes to make models OpenAPI-compatible.
146-
* **Type Mapping:** Maps Rust types (`Uuid`, `chrono::NaiveDateTime`, `Decimal`) back to OpenAPI formats automatically using the `TypeMapper` module.
147-
148-
### 3. Contract Safety (`test-gen`)
149-
Ensure your implementation actually matches the spec using the same strategies used for code generation.
150-
* **Test Generation:** Generates `tests/api_contracts.rs` based on your `openapi.yaml`.
151-
* **Smart Mocking:** Automatically fills request parameters with valid dummy data based on type signatures.
152-
* **Validation:** Verifies that API responses align with the JSON Schema defined in your spec.
165+
| Crate | Purpose |
166+
|----------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
167+
| **`cdd-core`** | **The Engine.** Contains the `ra_ap_syntax` parsers, the OpenAPI 3.x parser (with 3.2 shims), AST diffing logic, and the Backend Strategy traits (currently implementing `ActixStrategy`). |
168+
| **`cdd-cli`** | **The Interface.** Provides the `sync` and `test-gen` commands. |
169+
| **`cdd-web`** | **The Reference.** An Actix+Diesel implementation demonstrating the generated code and tests in action. |
153170

154-
---
171+
## 📦 CLI Usage
155172

156-
## 📦 Command Usage
173+
### 1. Sync Pipeline (DB ➔ Models)
157174

158-
### 1. The Sync Pipeline
159-
**DB ➔ Rust Models ➔ OpenAPI Attributes**
160-
Synchronizes your database schema to your Rust structs using the configured `ModelMapper`.
175+
Synchronize Diesel models and inject OpenAPI attributes.
161176

162177
```bash
163-
cargo run -p cdd-cli -- sync \
164-
--schema-path web/src/schema.rs \
178+
cargo run -p cdd-cli -- sync \
179+
--schema-path web/src/schema.rs \
165180
--model-dir web/src/models
166181
```
167182

168-
### 2. The Test Pipeline
169-
**OpenAPI ➔ Integration Tests**
170-
Generates a test suite via `BackendStrategy` (default: Actix) that treats your app as a black box.
183+
This performs the following:
184+
185+
1. Reads `schema.rs`.
186+
2. Generates rust structs in `models/` using `diesel/dsync` logic.
187+
3. **Patches** the files to add `#![allow(missing_docs)]`, `use utoipa::ToSchema;`, and derive macros.
188+
189+
### 2. Test Generation (OpenAPI ➔ Tests)
190+
191+
Scaffold integration tests to verify your implementation meets the contract.
171192

172193
```bash
173-
cargo run -p cdd-cli -- test-gen \
174-
--openapi-path docs/openapi.yaml \
175-
--output-path web/tests/api_contracts.rs \
194+
cargo run -p cdd-cli -- test-gen \
195+
--openapi-path docs/openapi.yaml \
196+
--output-path web/tests/api_contracts.rs \
176197
--app-factory crate::create_app
177198
```
178199

179-
---
200+
This generates a test file that:
201+
202+
1. Initializes your App factory.
203+
2. Iterates through every route in your OpenAPI spec.
204+
3. Sensibly mocks requests.
205+
4. Validates that your Rust implementation returns the headers and bodies defined in the YAML.
180206

181-
## 🛠 Project Structure
207+
## 🛠 OpenAPI Compliance
182208

183-
* **`core/`**: The engine. Contains AST parsers, strategies, and the diff/patch logic.
184-
* `strategies.rs`: Defines `BackendStrategy` trait and `ActixStrategy`.
185-
* `patcher.rs`: Surgical code editing.
186-
* `oas.rs`: Parses OpenAPI YAML into Intermediate Representations.
187-
* `handlers/routes/contract_test`: Functional modules utilizing strategies to generate code.
188-
* **`cli/`**: The workflow runner. Wires up specific strategies to commands.
189-
* `generator.rs`: Defines `ModelMapper` and `DieselMapper`.
190-
* `main.rs`: Dependency injection root.
191-
* **`web/`**: Reference implementation. An Actix Web + Diesel project demonstrating the generated code in action.
209+
`cdd-rust` features a highly compliant custom parser found in `core/src/oas`.
192210

193-
## 🎨 Design Principles
211+
* **Versions:** Supports OpenAPI 3.0 and 3.1 directly.
212+
* **Compatibility:** Implements shims for **OpenAPI 3.2**, specifically handling the `$self` keyword for Base URI
213+
determination (Appendix F) and downgrading version strings for library compatibility.
214+
* **Resolution:** Full support for local, relative, and remote `$ref` resolution.
215+
* **Polymorphism:** handles `oneOf`, `anyOf`, and `allOf` (flattening) into Rust Enums and Structs.
216+
* **Extractors:** Maps OAS parameters to backend-specific extractors (e.g., `web::Query`, `web::Path`, `web::Json`,
217+
`SecurityScheme`).
218+
219+
## Developer Guide
220+
221+
### Prerequisites
222+
223+
* Rust (Nightly toolchain required for `ra_ap_syntax` compatibility feature flags in some contexts).
224+
* PostgreSQL (if running the reference web implementation).
225+
226+
### Installation
227+
228+
```bash
229+
git clone https://github.com/offscale/cdd-rust
230+
cd cdd-rust
231+
cargo build
232+
```
233+
234+
### Running Tests
235+
236+
```bash
237+
# Run unit tests
238+
cargo test
239+
240+
# Run the generated contract tests (requires web/tests/api_contracts.rs to be generated)
241+
cargo test -p cdd-web
242+
```
243+
244+
## License
194245

195-
* **No Magic Folders:** We generate code you can read, debug, and commit.
196-
* **Lossless Patching:** We edit your source files without breaking your style.
197-
* **Pluggable Backend:** Core logic is decoupled from specific frameworks (Actix, Axum, etc.).
198-
* **Type Safety:** `Uuid`, `chrono`, and `rust_decimal` are first-class citizens.
246+
Licensed under either of Apache License, Version 2.0 or MIT license at your option.
199247

200248
---
201249

202250
## Developer guide
203251

204-
Install the latest version of [Rust](https://www.rust-lang.org). We tend to use nightly versions. [CLI tool for installing Rust](https://rustup.rs).
252+
Install the latest version of [Rust](https://www.rust-lang.org). We tend to use nightly
253+
versions. [CLI tool for installing Rust](https://rustup.rs).
205254

206255
We use [rust-clippy](https://github.com/rust-lang-nursery/rust-clippy) linters to improve code quality.
207256

cli/Cargo.toml

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,12 @@ edition = "2021"
55

66
[dependencies]
77
cdd-core = { path = "../core" }
8-
clap = { version = "4.4", features = ["derive"] }
9-
dsync = "0.1.0"
10-
walkdir = "2.5.0"
8+
clap = { version = "^4", features = ["derive"] }
9+
dsync = "^0.1"
10+
walkdir = "^2.5"
1111
derive_more = { version = "^2.1", features = ["from", "display"] }
12+
serde_json = { version = "^1", features = ["indexmap"] }
13+
serde_yaml = "^0.9"
1214

1315
[dev-dependencies]
14-
tempfile = "3.8"
16+
tempfile = "^3"

cli/src/main.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
//! Supported Commands:
88
//! - `sync`: Pipeline DB -> Diesel -> Model -> Schema -> OpenAPI.
99
//! - `test-gen`: Generates integration tests from OpenAPI specs.
10+
//! - `scaffold`: Generates handler scaffolding from OpenAPI specs.
11+
//! - `schema-gen`: Generates JSON Schemas from Rust structs.
1012
1113
use cdd_core::strategies::ActixStrategy;
1214
use cdd_core::AppResult;
@@ -16,6 +18,8 @@ use crate::generator::DieselMapper;
1618

1719
mod error;
1820
mod generator;
21+
mod scaffold;
22+
mod schema_gen;
1923
mod sync;
2024
mod test_gen;
2125

@@ -32,6 +36,11 @@ enum Commands {
3236
Sync(sync::SyncArgs),
3337
/// Generates integration tests based on OpenAPI contracts.
3438
TestGen(test_gen::TestGenArgs),
39+
/// Scaffolds handler functions from OpenAPI Routes.
40+
Scaffold(scaffold::ScaffoldArgs),
41+
/// Generates a JSON Schema from a Rust struct or enum.
42+
#[clap(name = "schema-gen")]
43+
SchemaGen(schema_gen::SchemaGenArgs),
3544
}
3645

3746
fn main() -> AppResult<()> {
@@ -48,6 +57,14 @@ fn main() -> AppResult<()> {
4857
let strategy = ActixStrategy;
4958
test_gen::execute(args, &strategy)?;
5059
}
60+
Commands::Scaffold(args) => {
61+
// Injecting Actix Web strategy
62+
let strategy = ActixStrategy;
63+
scaffold::execute(args, &strategy)?;
64+
}
65+
Commands::SchemaGen(args) => {
66+
schema_gen::execute(args)?;
67+
}
5168
}
5269

5370
Ok(())

0 commit comments

Comments
 (0)