|
1 | | -cdd-rust |
2 | | --------- |
3 | | -[](http://unmaintained.tech) |
| 1 | +cdd-rust: OpenAPI ↔ Rust |
| 2 | +======================== |
4 | 3 | [](https://www.rust-lang.org) |
5 | 4 | [](LICENSE-APACHE) |
6 | 5 | [](https://github.com/offscale/cdd-rust/actions/workflows/ci-cargo.yml) |
7 | 6 |
|
8 | | -Update: future of this repo remains unclear. Probably restart, delete all [non `.git`] files|folders and do a `cargo init`. One direction—different to the [Python](https://github.com/offscale/cdd-python) and [C](https://github.com/SamuelMarks/cdd-c) [cdd](https://compilers.com.au) implementations—is to go from: |
| 7 | +**Compiler Driven Development (CDD)** for Rust. |
9 | 8 |
|
10 | | -0. SQL to [diesel](https://diesel.rs) ([`diesel::table!`](https://docs.rs/diesel/latest/diesel/macro.table.html)); |
11 | | -1. [`diesel::table!`](https://docs.rs/diesel/latest/diesel/macro.table.html) to diesel `struct`s and functions (https://github.com/SamuelMarks/dsync); then |
12 | | -2. Diesel `struct`s to/fro [JSON-schema](https://json-schema.org/specification) via a new custom parser/emitter (compiler) written with https://github.com/rust-lang/rust-analyzer |
| 9 | +**cdd-rust** bridges the gap between your **Database**, **Rust Code**, and **OpenAPI Specifications**. Unlike traditional generators that produce untouchable code in a "generated" folder, `cdd-rust` uses advanced AST parsing to surgically patch your *existing* source files, strictly Typed handlers, and integration tests. |
13 | 10 |
|
14 | | -Next, realise [JSON-schema](https://json-schema.org/specification) as part of a greater [OpenAPI](https://spec.openapis.org/oas/latest.html), and implement custom [rust-analyzer](https://github.com/rust-lang/rust-analyzer) parser/emitter code to go from/to: |
| 11 | +## ⚡️ The CDD Loop |
15 | 12 |
|
16 | | -3. [actix](https://actix.rs); |
17 | | -4. tests & mocks; |
18 | | -5. OpenAPI [dynamic: [utoipa](https://github.com/juhaku/utoipa); static: custom]. |
| 13 | +Automate the repetitive parts of building robust web services with **Actix Web**, **Diesel**, and **Postgres**. |
| 14 | + |
| 15 | +```mermaid |
| 16 | +%%{init: { |
| 17 | + 'theme': 'base', |
| 18 | + 'themeVariables': { |
| 19 | + 'primaryColor': '#ffffff', |
| 20 | + 'primaryTextColor': '#20344b', |
| 21 | + 'primaryBorderColor': '#20344b', |
| 22 | + 'lineColor': '#20344b', |
| 23 | + 'fontFamily': 'Google Sans, sans-serif' |
| 24 | + } |
| 25 | +}}%% |
| 26 | +
|
| 27 | +graph TD |
| 28 | +%% Nodes |
| 29 | + OpenAPI([OpenAPI]):::yellow |
| 30 | + Handlers(Actix Handlers):::blue |
| 31 | + Models(Diesel Models):::green |
| 32 | + DB[(Database)]:::navy |
| 33 | +
|
| 34 | +%% Flow 0 & 1: Downward (Scaffold & Patch) |
| 35 | + OpenAPI -->|"0. Scaffold (New) | 1. Patch (Existing)"| Handlers |
| 36 | +
|
| 37 | +%% Connection |
| 38 | + Handlers -- "Uses Strictly Typed Structs" --> Models |
| 39 | +
|
| 40 | +%% Flow 2: Upward (Reflection) |
| 41 | + Models -.->|"2. Derives Schema (Reflection)"| OpenAPI |
| 42 | +
|
| 43 | +%% Database Sync |
| 44 | + DB == "Syncs SQL Columns" ==> Models |
| 45 | +
|
| 46 | +%% Styles |
| 47 | + classDef yellow fill:#f9ab00,stroke:#20344b,stroke-width:2px,color:#ffffff,font-family:'Google Sans Medium',font-size:16px; |
| 48 | + classDef blue fill:#4285f4,stroke:#20344b,stroke-width:2px,color:#ffffff,font-family:'Google Sans Medium',font-size:16px; |
| 49 | + classDef green fill:#34a853,stroke:#20344b,stroke-width:2px,color:#ffffff,font-family:'Google Sans Medium',font-size:16px; |
| 50 | + classDef navy fill:#20344b,stroke:#20344b,stroke-width:2px,color:#ffffff,font-family:'Google Sans Medium',font-size:16px; |
| 51 | +
|
| 52 | + linkStyle default stroke:#20344b,stroke-width:2px; |
| 53 | +``` |
| 54 | + |
| 55 | +--- |
| 56 | + |
| 57 | +## 🚀 The Philosophy |
| 58 | + |
| 59 | +**Compiler Driven Development** solves synchronization issues across language boundaries (Backend $\leftrightarrow$ Frontend $\leftrightarrow$ Docs). |
| 60 | + |
| 61 | +* **Single Source of Truth:** Your Code + Attributes *are* the documentation. Your Database *is* the source of your models. |
| 62 | +* **No Magic Folders:** We don't hide code. We generate code you can read, debug, and commit. |
| 63 | +* **Lossless Patching:** Powered by `ra_ap_syntax` (Rust Analyzer), we edit your files without breaking your manual formatting or comments. |
| 64 | +* **Contract Safety:** Automated updating of contract tests ensures your implementation strictly adheres to the API definition. |
| 65 | + |
| 66 | +--- |
| 67 | + |
| 68 | +## 🛠 Features |
| 69 | + |
| 70 | +### 1. Database & Model Sync (`sync`) |
| 71 | +Keeps your Rust structs in perfect harmony with your Postgres schema. |
| 72 | +* **Diesel Integration:** Wraps `dsync` to generate raw structs from `schema.rs`. |
| 73 | +* **Attribute Injection:** Automatically parses generated structs and injects `utoipa::ToSchema`, `serde::Serialize`, and `serde::Deserialize`. |
| 74 | +* **Result:** A fully documented, OpenAPI-ready Rust struct generated directly from your DB. |
| 75 | + |
| 76 | +### 2. Contract Test Generation (`test-gen`) |
| 77 | +Treats your application as a black box to ensure spec compliance. |
| 78 | +* **Route Parsing:** Reads your `openapi.yaml`. |
| 79 | +* **Test Scaffolding:** Generates `tests/api_contracts.rs` containing `#[actix_web::test]` functions. |
| 80 | +* **Smart Mocking:** Automatically generates dummy values for `Uuid`, `Date`, and primitives to satisfy route parameters during testing. |
| 81 | +* **Schema Validation:** Includes logic to validate response bodies against the JSON Schema definitions. |
| 82 | + |
| 83 | +### 3. AST-Based Patching (Core) |
| 84 | +The engine under the hood (`cdd-core`) provides intelligent code manipulation: |
| 85 | +* **Smart Injection:** Adds fields to structs and lines to functions respecting indentation and comma placement. |
| 86 | +* **Structural Diffing:** configuration-aware diffing between target specs and actual implementations. |
| 87 | +* **Route Registration:** Injects `cfg.service(...)` calls into your Actix config without disrupting existing logic. |
| 88 | + |
| 89 | +--- |
| 90 | + |
| 91 | +## 📦 Usage |
| 92 | + |
| 93 | +### Installation |
| 94 | + |
| 95 | +Clone the repository and build the CLI tool: |
| 96 | + |
| 97 | +```bash |
| 98 | +cargo build -p cdd-cli --release |
| 99 | +``` |
| 100 | + |
| 101 | +### Command Reference |
| 102 | + |
| 103 | +#### 1. Sync Pipeline (DB ➔ Rust ➔ OpenAPI) |
| 104 | +Transforms raw Diesel schema files into rich, OpenAPI-compatible Rust structs. |
| 105 | + |
| 106 | +```bash |
| 107 | +# Workflow: |
| 108 | +# 1. Runs `dsync` to update models from schema.rs |
| 109 | +# 2. Patches models with #[derive(ToSchema)] |
| 110 | +cargo run -p cdd-cli -- sync \ |
| 111 | + --schema-path web/src/schema.rs \ |
| 112 | + --model-dir web/src/models |
| 113 | +``` |
| 114 | + |
| 115 | +#### 2. Test Configuration (OpenAPI ➔ Tests) |
| 116 | +Reads your API definition and writes a Rust test suite. |
| 117 | + |
| 118 | +```bash |
| 119 | +cargo run -p cdd-cli -- test-gen \ |
| 120 | + --openapi-path docs/openapi.yaml \ |
| 121 | + --output-path web/tests/api_contracts.rs \ |
| 122 | + --app-factory crate::create_app |
| 123 | +``` |
19 | 124 |
|
20 | 125 | --- |
21 | 126 |
|
22 | | -OpenAPI ↔ Rust. Compiler Driven Development (CDD) is a new development methodology, with implementations in many languages. |
| 127 | +## 🏗 Project Structure |
23 | 128 |
|
24 | | -The central idea is to statically code-generate from target language to OpenAPI, and from OpenAPI back to target language. |
25 | | -All without having an untouchable 'generated' directory and without requiring `#[openapi]` annotations on `struct`s and routes. |
| 129 | +* **`core/`**: The brain of the operation. Contains AST parsers (`ra_ap_syntax`), OpenAPI parsers, and code patching logic. It performs surgical updates on Rust source files. |
| 130 | +* **`cli/`**: The automation runner. Orchestrates `diesel`, `dsync`, and the core library to execute pipelines. |
| 131 | +* **`web/`**: The reference implementation. A standard Actix Web project that demonstrates how generated models and tests live alongside hand-written logic. |
26 | 132 |
|
27 | | -Key other advantages are: |
| 133 | +## 🎨 Design Principles |
28 | 134 |
|
29 | | - - automated updating of tests and docs, making it feasible to maintain 100% coverage without trading off development agility; |
30 | | - - synchronisation across language boundaries (e.g., between the frontends, and from them to the backend). |
| 135 | +* **Non-Destructive:** We respect your existing code style, comments, and spacing. |
| 136 | +* **Type Safety:** `Uuid`, `jso::serde::Value`, and `chrono::DateTime` are first-class citizens. |
| 137 | +* **Dependencies:** |
| 138 | + * **Actix Web:** For the HTTP layer. |
| 139 | + * **Diesel:** For ORM/DB layer. |
| 140 | + * **Utoipa:** For OpenAPI attribute generation. |
| 141 | + * **Ra_ap_syntax:** For 100% accurate code manipulation. |
31 | 142 |
|
32 | | -Longer-term there are many other advantages, including: |
| 143 | +## 🔮 Roadmap |
33 | 144 |
|
34 | | - - inversion of control, enabling the business analyst to design schemas (Google Forms or even MS Access style); |
35 | | - - simplifying separating projects out into multiple smaller projects, and smaller projects into a big project; |
36 | | - - providing an alternative to NoSQL for many user-defined schema scenarios (such as a survey-builder site). |
| 145 | +- [x] Structural Diffing & AST Patching |
| 146 | +- [x] Database Model Synchronization |
| 147 | +- [x] Contract Test Generation |
| 148 | +- [x] Handler Scaffolding (Core Library Support) |
| 149 | +- [ ] Visual Schema Designer Integration |
| 150 | +- [ ] Expose Handler Scaffolding via CLI |
37 | 151 |
|
38 | 152 | --- |
39 | 153 |
|
|
0 commit comments