Skip to content

Commit 0eec91e

Browse files
committed
JSON-RPC server, Dockerfiles, and CLI & doc improvements
1 parent 17591db commit 0eec91e

51 files changed

Lines changed: 2085 additions & 528 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/ci-cargo.yml

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,13 @@ name: CI
33
on:
44
push:
55
branches: [ "master" ]
6+
tags:
7+
- 'v*'
68
pull_request:
79
branches: [ "master" ]
810

911
env:
1012
CARGO_TERM_COLOR: always
11-
# Ensure we don't need a real DB for basic unit tests
1213
DATABASE_URL: postgres://user:password@localhost/dummy
1314

1415
jobs:
@@ -17,11 +18,11 @@ jobs:
1718
runs-on: ubuntu-latest
1819

1920
steps:
20-
- uses: actions/checkout@v6
21+
- uses: actions/checkout@v4
2122

2223
- name: Set up Rust
2324
run: |
24-
rustup override set nightly
25+
rustup override set stable
2526
rustup component add rustfmt
2627
rustup component add clippy
2728
@@ -32,13 +33,17 @@ jobs:
3233
run: cargo clippy --workspace -- -D warnings
3334

3435
- name: Build Workspace
35-
run: cargo build --verbose --workspace
36+
run: cargo build --verbose --workspace --release
37+
38+
- name: Build WASM
39+
run: |
40+
rustup target add wasm32-unknown-unknown
41+
cargo build -p cdd-cli --release --target wasm32-unknown-unknown --verbose
3642
3743
- name: Run Tests
3844
run: cargo test --verbose --workspace
3945

4046
- name: Check Documentation
41-
# This compiles the docs and respects #![deny(missing_docs)]
4247
run: cargo doc --workspace --no-deps --document-private-items
4348
env:
4449
RUSTDOCFLAGS: "-D warnings"
@@ -47,5 +52,12 @@ jobs:
4752
run: cargo install cargo-tarpaulin
4853

4954
- name: Run Test Coverage
50-
# Enforces 100% test coverage across the workspace
5155
run: cargo tarpaulin --fail-under 100 --workspace --out xml
56+
57+
- name: Upload artifacts (if tag)
58+
if: startsWith(github.ref, 'refs/tags/v')
59+
uses: softprops/action-gh-release@v1
60+
with:
61+
files: |
62+
target/release/cdd-rust
63+
target/wasm32-unknown-unknown/release/cdd-rust.wasm

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
/out
12
/target
23
/Cargo.lock
34
.idea

ARCHITECTURE.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ graph TD
5858

5959
The Frontend's responsibility is to read an input source and translate it into the universal CDD Intermediate Representation (IR).
6060

61-
* **Static Analysis (AST-Driven)**: For `Rust` source code, the tool **does not** use dynamic reflection or execute the code. Instead, it reads the source files, generates an Abstract Syntax Tree (AST) using `ra_ap_syntax` (from rust-analyzer), and navigates the tree to extract classes, structs, functions, type signatures, API client definitions, server routes, and docstrings.
61+
* **Static Analysis (AST-Driven)**: For `Rust` source code, the tool **does not** use dynamic reflection or execute the code. Instead, it reads the source files, generates an Abstract Syntax Tree (AST) using `ra_ap_syntax`, and navigates the tree to extract classes, structs, functions, type signatures, API client definitions, server routes, and docstrings.
6262
* **OpenAPI Parsing**: For OpenAPI and JSON Schema inputs, the parser normalizes the structure, resolving internal `$ref`s and extracting properties, endpoints (client or server perspectives), and metadata into the IR.
6363

6464
### 2. Intermediate Representation (IR)
@@ -74,15 +74,15 @@ By standardizing on a single IR (heavily inspired by OpenAPI / JSON Schema primi
7474

7575
The Backend's responsibility is to take the universal IR and generate valid target output. Emitters can be written to support various environments (e.g., Client vs Server, Web vs CLI).
7676

77-
* **Code Generation**: Emitters iterate over the IR and generate idiomatic `Rust` source code.
78-
* A **Server Emitter** creates routing controllers and request-validation logic using `actix-web`.
79-
* A **Client Emitter** can generate documentation snippets or test configurations.
80-
* **Database & CLI Generation**: Emitters can also target ORM models (via `dsync` for Diesel) or command-line parsers by mapping IR properties to database columns or CLI arguments.
81-
* **Specification Generation**: Emitters translating back to OpenAPI serialize the IR into standard OpenAPI 3.x JSON or YAML, rigorously formatting descriptions, type constraints, and endpoint schemas based on what was parsed from the source code.
77+
* **Code Generation**: Emitters iterate over the IR and generate idiomatic `Rust` source code using token replacement and syntax manipulation.
78+
* A **Server Emitter** creates routing controllers and request-validation logic.
79+
* A **Client Emitter** creates API wrappers, fetch functions, and response-parsing logic.
80+
* **Database & CLI Generation**: Emitters can also target ORM models or command-line parsers by mapping IR properties to database columns or CLI arguments.
81+
* **Specification Generation**: Emitters translating back to OpenAPI serialize the IR into standard OpenAPI 3.2.0 JSON or YAML, rigorously formatting descriptions, type constraints, and endpoint schemas based on what was parsed from the source code.
8282

8383
## 🔄 Extensibility
8484

85-
Because of the IR-centric design, adding support for a new `Rust` framework (e.g., a new Client library, Web framework, or ORM) requires minimal effort:
85+
Because of the IR-centric design, adding support for a new `Rust` framework (e.g., a new Client library, Web framework like Axum/Actix, or ORM like Diesel/SeaORM) requires minimal effort:
8686
1. **To support parsing a new framework**: Write a parser that converts the framework's AST/DSL into the CDD IR. Once written, the framework can automatically be exported to OpenAPI, Client SDKs, CLI parsers, or any other existing output target.
8787
2. **To support emitting a new framework**: Write an emitter that converts the CDD IR into the framework's DSL/AST. Once written, the framework can automatically be generated from OpenAPI or any other supported input.
8888

@@ -91,4 +91,4 @@ Because of the IR-centric design, adding support for a new `Rust` framework (e.g
9191
1. **A Single Source of Truth**: Developers should be able to maintain their definitions in whichever format is most ergonomic for their team (OpenAPI files, Native Code, Client libraries, ORM models) and generate the rest.
9292
2. **Zero-Execution Parsing**: Ensure security and resilience by strictly statically analyzing inputs. The compiler must never need to run the target code to understand its structure.
9393
3. **Lossless Conversion**: Maximize the retention of metadata (e.g., type annotations, docstrings, default values, validators) during the transition `Source -> IR -> Target`.
94-
4. **Symmetric Operations**: An Endpoint in the IR holds all the information necessary to generate both the Server-side controller that fulfills it, and the Client-side SDK method that calls it.
94+
4. **Symmetric Operations**: An Endpoint in the IR holds all the information necessary to generate both the Server-side controller that fulfills it, and the Client-side SDK method that calls it.

COMPLIANCE.md

Lines changed: 8 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -1,116 +1,11 @@
1-
# OpenAPI 3.2.0 Compliance
1+
# OpenAPI Compliance
22

3-
`cdd-rust` has achieved **100% compliance** with the features introduced in the OpenAPI 3.2.0 specification. It features a highly compliant custom parser found in `core/src/oas`.
3+
This tool targets OpenAPI 3.2.0.
44

5-
## Strict Code Standards
5+
Currently, it parses and emits a core subset of OpenAPI 3.2.0 including:
6+
- Info block
7+
- Servers block
8+
- Paths (Operations, Parameters, Responses, Request Bodies)
9+
- Components (Schemas)
610

7-
As part of maintaining high compliance standards, `cdd-rust` strictly adheres to **100% Test Coverage** and **100% Documentation Coverage** across all source files. No `exclude-files` or coverage-bypassing exceptions (e.g., `#![cfg(not(tarpaulin_include))]` or `#![allow(missing_docs)]`) are permitted.
8-
9-
## Supported Workflows
10-
11-
- **Codebase ➔ OpenAPI:** Partially supported natively. The CLI automatically prepares database models for OpenAPI generation (`sync`) and can generate OpenAPI schemas for standalone Rust structs (`schema-gen`). The full OpenAPI routing document is usually built at compile time via ecosystem crates like `utoipa`.
12-
- **OpenAPI ➔ Codebase (Scaffold New):** Fully supported. The `scaffold` command can generate all necessary modules, handler functions, payloads, and `.service()` registrations. The `test-gen` command writes integration tests.
13-
- **OpenAPI ➔ Codebase (Merge Existing):** Fully supported via AST-aware patching. `cdd-rust` safely merges new routes and modifications without overwriting existing handwritten code.
14-
15-
## Implementation Details
16-
17-
* **Versions:** Supports OpenAPI 3.0, 3.1, and 3.2 directly.
18-
* **Compatibility:** Implements shims for **OpenAPI 3.2**, specifically handling the `$self` keyword for Base URI
19-
determination (Appendix F) and downgrading version strings for library compatibility if needed.
20-
* **Relative `$self`:** Resolves relative `$self` values (including dot-segment normalization) when matching local
21-
`$ref` targets and `operationRef` pointers.
22-
* **Validation:** Enforces required `info`, URI/email formatting for Info/Contact/License, leading-slash `paths`,
23-
unique `operationId` values, templated path conflicts, component key naming rules, response status code keys,
24-
security scheme definitions, security requirement resolution, non-empty `response.description` and `requestBody.content`,
25-
mutual exclusivity of `example` vs `examples` for parameters/headers, sequential-only use of `itemSchema`,
26-
and rejects `additionalOperations` that reuse reserved HTTP methods.
27-
* **Resolution:** Local `$ref` resolution plus base-URI-aware absolute/relative self-references (no external fetch).
28-
* **Multi-Document `$ref`:** Optional `DocumentRegistry` resolves external OpenAPI/Schema documents (path items,
29-
parameters, request bodies, responses, headers, links, media types, and security schemes) plus schema
30-
`$id`/`$anchor` targets.
31-
* **Schema `$id` References:** Resolves schema `$ref` values that match component or inline `$id`
32-
URIs (absolute or resolved against `$self`).
33-
* **Schema Anchors:** Resolves `$anchor` / `$dynamicAnchor` targets for component or inline
34-
schemas and resolves `$dynamicRef` using dynamic anchor scope (falling back to standard `$ref` resolution).
35-
* **Relative Server URLs:** Resolves relative `servers.url` values (e.g., `.`, `./v1`, `v1`) into base paths with RFC3986 dot-segment normalization, using the retrieval URI when provided.
36-
* **Polymorphism:** handles `oneOf`, `anyOf`, and `allOf` (flattening) into Rust Enums and Structs.
37-
* **Discriminator Defaults:** supports `discriminator.defaultMapping` for OAS 3.2 polymorphic schemas.
38-
* **Extractors:** Maps OAS parameters to backend-specific extractors (e.g., `web::Query`, `web::Path`, `web::Json`,
39-
`SecurityScheme`).
40-
* **Media Types:** Recognizes vendor `+json` media types, `text/*`, and binary request bodies with dedicated extractors.
41-
* **Media Type References:** Resolves `components.mediaTypes` `$ref` entries inside `content` (request bodies, responses, and headers).
42-
* **Parameter Content Media Types:** Resolves `components.mediaTypes` `$ref` in parameter `content`, supports `itemSchema` for sequential media types, and honors `serializedValue`/`externalValue` examples.
43-
* **Content Schema Mapping:** Uses `contentSchema` (for JSON-encoded string payloads) to drive strong typing for parameters and request bodies.
44-
* **Sequential Multipart:** supports `multipart/mixed` and `multipart/byteranges` `itemSchema` normalization.
45-
* **Positional Encoding:** parses `prefixEncoding` / `itemEncoding` for multipart media types (OAS 3.2).
46-
* **Nested Encoding:** parses and emits nested Encoding Object `encoding` / `prefixEncoding` / `itemEncoding` fields.
47-
* **Examples:** Uses parameter `content` examples when generating contract tests, and honors
48-
`dataValue` / `serializedValue` / `externalValue` for parameters and request bodies (serialized examples bypass re-encoding).
49-
* **Sequential Media Types:** Supports `itemSchema` for sequential JSON request bodies (e.g., `jsonl`, `ndjson`) and maps to `Vec<T>`.
50-
* **Sequential Response Types:** Uses `itemSchema` for sequential media types (including `text/event-stream` and `multipart/*`) to infer `Vec<T>` when no `schema` is present.
51-
* **Sequential Vendor Suffixes:** Treats `+jsonl`, `+ndjson`, and `+json-seq` media types as sequential for `itemSchema` typing.
52-
* **Response Validation:** Contract tests validate JSON, vendor `+json`, sequential JSON, and `text/event-stream` responses.
53-
* **Response Headers:** Resolves response header `$ref` and `content` definitions when extracting response metadata.
54-
* **Response Header Content Priority:** Prefers `content` (or preserved `x-cdd-content`) over injected `schema` when parsing
55-
response header media types, ensuring `content`-based headers round-trip correctly.
56-
* **Response Header Content Round-Trip:** Preserves header `content` media types (and examples) when generating OpenAPI.
57-
* **Response Summary:** Preserves Response Object `summary` during parsing and OpenAPI generation (including callbacks).
58-
* **Schema Dialects:** Contract tests select JSON Schema draft via `jsonSchemaDialect` or per-schema `$schema` (defaults to Draft 2020-12 for OAS 3.1/3.2, Draft 4 for OAS 3.0/Swagger 2.0).
59-
* **Header Arrays/Objects:** Contract tests validate `schema`-based header arrays/objects using `style: simple` (explode and non-explode).
60-
* **Reference Overrides:** Honors Reference Object `description` overrides for responses during validation and resolution.
61-
* **Set-Cookie Handling:** Validates `Set-Cookie` headers without comma-splitting, preserving cookie values that contain commas.
62-
* **Querystring:** Serializes `querystring` params
63-
as JSON when the media type is `application/json` (RFC3986-encoded).
64-
* **Querystring Extractors:** Non-form querystring parameters are surfaced as raw `String` values
65-
in generated handlers to avoid incorrect form decoding; form-encoded querystrings remain typed.
66-
* **Header/Cookie Params:** Contract tests serialize header/cookie parameters using OAS `style`/`explode` rules or `content` media types.
67-
* **Header Validation:** Enforces Header Object constraints (`schema` vs `content`, `style: simple`, no `allowEmptyValue`), and ignores `Content-Type` headers.
68-
* **Media Type Examples:** Validates `example` vs `examples` mutual exclusivity in request/response content.
69-
* **Component Media Types:** Validates `components.mediaTypes` example conflicts and encoding field compatibility.
70-
* **Serialized/External Examples:** Preserves `serializedValue` and `externalValue` examples when generating OpenAPI for parameters and request bodies.
71-
* **Example Metadata:** Preserves Example Object `summary` and `description` when round-tripping examples.
72-
* **Example Ref Overrides:** Applies Reference Object `summary`/`description` overrides when resolving Example `$ref` values.
73-
* **Boolean Schemas:** Handles `schema: true/false` in request/response bodies and response headers (rejects required `false` bodies).
74-
* **Nullable Normalization:** Converts `nullable` / `x-nullable` into `type: [..., "null"]` for OpenAPI → Rust typing.
75-
* **Byte/Binary Formats:** Maps `format: byte` / `format: binary` to `Vec<u8>` in OpenAPI → Rust type mapping.
76-
* **Boolean Parameter Schemas:** Accepts `schema: true` for parameters (maps to `String`) and rejects `schema: false`.
77-
* **Example Precedence:** Honors `serializedValue` / `externalValue` examples for parameters even when `value` is present.
78-
* **Style Validation:** Enforces type constraints for `deepObject`, `spaceDelimited`, and `pipeDelimited` parameter styles.
79-
* **Schema ExternalDocs:** emits `externalDocs` metadata when generating OpenAPI schemas from Rust models.
80-
* **Schema ExternalDocs Validation:** Validates `externalDocs.url` on schema objects (including nested schemas).
81-
* **Schema XML Validation:** Validates schema `xml` objects, including `nodeType` values and conflicts with deprecated
82-
`attribute` / `wrapped` fields.
83-
* **Serde Mapping:** respects `rename_all` and `deny_unknown_fields` when generating OpenAPI schemas from Rust models.
84-
* **Link Servers:** Applies Link Object `server` overrides (including defaulted variables) when generating HATEOAS link construction code.
85-
* **Link Server Metadata:** Preserves Link Object `server` details (name/description/variables) when generating OpenAPI.
86-
* **Link Validation:** Resolves `operationRef` pointers to concrete path+method targets and errors on unknown `operationId` links.
87-
* **Link Components:** Resolves `operationRef` pointers to `components.pathItems` when the component is referenced by a
88-
unique path (errors on ambiguity).
89-
* **Link Round-Trip:** Resolves `operationId`/`operationRef` targets for codegen without mutating the original Link Object,
90-
avoiding invalid `operationId`+`operationRef` emissions during OpenAPI generation.
91-
* **Link Validation (Local Ref):** Errors when a local `operationRef` fails to resolve to a known operation.
92-
* **Link Object Validation:** Enforces exactly one of `operationId` or `operationRef`, validates Link Object `server` definitions, enforces link name key patterns, and detects link `$ref` cycles.
93-
* **Link Parameter Keys:** Validates qualified Link `parameters` keys (e.g., `path.id`) and substitutes them into link templates using the unqualified parameter name.
94-
* **Link Parsing:** Accepts normalized snake_case link keys (`operation_id`, `operation_ref`, `request_body`) during YAML preprocessing.
95-
* **OAuth2/OIDC Schemes:** Preserves OAuth2 flows (including device authorization) and OpenID Connect discovery URLs when generating OpenAPI.
96-
* **Contract Tests:** Skips webhook routes (inbound) during test generation.
97-
* **Contract Tests (Multipart):** Builds multipart request payloads from example values and per-part `contentType` hints.
98-
* **Contract Tests (Encoding Headers):** Applies `Encoding` object headers to multipart parts (excluding `Content-Type`) and respects `Encoding.contentType` for JSON-form-urlencoded fields.
99-
* **Encoding Header Refs:** Resolves `Encoding.headers` `$ref` entries against `components.headers` when extracting request body definitions.
100-
* **Callbacks:** Enforces `operationId` uniqueness across callbacks and top-level operations.
101-
* **Callback Parameters:** Parses callback Path Item and Operation parameters, merging them for callback operations and emitting them during OpenAPI generation.
102-
* **Top-Level Security:** Preserves root-level `security` requirements when generating OpenAPI documents.
103-
* **Operation Security Overrides:** Preserves explicit operation-level `security` (including empty arrays) without
104-
leaking global security into each operation during OpenAPI round-trips.
105-
* **Callback Security:** Parses and emits callback operation `security` requirements (including inherited defaults).
106-
* **Header Parameter Case:** Treats header parameter names as case-insensitive when detecting duplicates.
107-
* **OpenAPI Generation:** Emits top-level `tags` and `servers` (or per-operation `servers`) from parsed routes.
108-
* **Round-Trip Metadata:** Preserves original `operationId` values and selected response status/description/media type in generated OpenAPI (including callbacks).
109-
* **Document Metadata Round-Trip:** `parse_openapi_document` extracts `$self`, `jsonSchemaDialect`, `info`, `servers`, `tags`, `externalDocs`, and root-level `x-` extensions for OpenAPI → Rust → OpenAPI workflows.
110-
* **Component Preservation:** Can merge existing `components` (responses, examples, mediaTypes, etc.) when generating OpenAPI.
111-
* **Schema Keyword Passthrough:** Preserves advanced JSON Schema keywords (`if/then/else`, `dependentSchemas`, `unevaluatedProperties`, `contentSchema`) across parameters, request/response bodies, and component schemas during OpenAPI ↔ Rust round-trips.
112-
* **Paths/Webhooks Extensions:** Accepts `x-` keys at the `paths` and `webhooks` object level without treating them as path items,
113-
and preserves them during OpenAPI generation.
114-
* **Path Item Extensions:** Preserves `x-` extensions on Path Item Objects during OpenAPI ↔ Rust round-trips.
115-
* **Server Override Round-Trip:** Preserves path/operation-level `servers` objects (including variables) instead of collapsing to base paths.
116-
* **Server URL Validation:** Rejects invalid URI references in `servers.url` (including whitespace in literal segments).
11+
Compliance is continuously expanding to cover the entire specification.

0 commit comments

Comments
 (0)