The XDK (X Development Kit) Generator is a powerful, language-agnostic SDK generation system that automatically creates Software Development Kits (SDKs) for the X API from OpenAPI 3.0 specifications. The system is designed with extensibility and maintainability at its core, using a macro-driven approach to minimize boilerplate while maximizing consistency across different target languages.
graph TB
subgraph "Input"
OAS[OpenAPI 3.0 Specification]
end
subgraph "XDK Core Libraries"
Parser[xdk-openapi<br/>Parser & Reference Resolution]
Lib[xdk-lib<br/>Models & Utilities]
Gen[xdk-gen<br/>Language Generators]
Build[xdk-build<br/>CLI Tool]
end
subgraph "Language! Macro System"
Macro[language! macro]
Config[Language Configuration<br/>• Casing Rules<br/>• Template Filters<br/>• Render Specs]
end
subgraph "Processing Pipeline"
Extract[Extract Operations<br/>Group by Tags]
Transform[Apply Casing<br/>Transform Data Models]
Render[Render Templates<br/>with Context]
end
subgraph "Template System"
Templates[Jinja2 Templates<br/>• models.j2<br/>• client.j2<br/>• tests.j2]
Filters[Template Filters<br/>• Type Conversion<br/>• Naming Helpers]
end
subgraph "Output"
SDK[Generated SDK<br/>• Client Libraries<br/>• Data Models<br/>• Test Suites]
Files[File Structure<br/>• Language-specific layout<br/>• Package metadata]
end
OAS --> Parser
Parser --> Lib
Lib --> Extract
Macro --> Config
Config --> Gen
Gen --> Transform
Extract --> Transform
Transform --> Render
Templates --> Render
Filters --> Render
Render --> SDK
SDK --> Files
Build --> Gen
classDef input fill:#e1f5fe
classDef core fill:#f3e5f5
classDef macro fill:#fff3e0
classDef process fill:#e8f5e8
classDef template fill:#fff8e1
classDef output fill:#fce4ec
class OAS input
class Parser,Lib,Gen,Build core
class Macro,Config macro
class Extract,Transform,Render process
class Templates,Filters template
class SDK,Files output
The heart of the XDK generator is the language! macro, which allows developers to declaratively define an entire SDK generator for any programming language in a single, concise specification:
language! {
name: Python,
filters: [pascal_case, python_type, last_part],
class_casing: Casing::Pascal,
operation_casing: Casing::Snake,
import_casing: Casing::Snake,
variable_casing: Casing::Snake,
render: [
multiple {
render "models" => "xdk/{}/models.py",
render "client_class" => "xdk/{}/client.py",
render "client_module" => "xdk/{}/__init__.py"
},
render "main_client" => "xdk/client.py",
render "oauth2_auth" => "xdk/oauth2_auth.py",
render "init_py" => "xdk/__init__.py"
],
tests: [
multiple {
render "test_contracts" => "tests/{}/test_contracts.py",
render "test_structure" => "tests/{}/test_structure.py",
render "test_pagination" => "tests/{}/test_pagination.py"
},
render "conftest" => "tests/conftest.py"
]
}This single declaration generates a complete, functional SDK generator that:
- Parses OpenAPI specifications
- Applies language-specific naming conventions
- Generates client libraries, models, and comprehensive test suites
- Handles complex scenarios like pagination, authentication, and error handling
The XDK architecture separates concerns into distinct, reusable layers:
- Custom OpenAPI 3.0 parser with lazy reference resolution
- Strongly-typed representation of API specifications
- Support for complex schemas, inheritance, and component references
- Extracts operations, parameters, and schemas from OpenAPI specs
- Groups operations by tags for modular SDK organization
- Applies language-specific naming conventions consistently
- Generates comprehensive metadata for template rendering
- MiniJinja-powered templating system
- Language-specific filters and helpers
- Context-aware rendering with rich data models
- Support for conditional logic and complex iterations
- Automatic generation of multiple test types:
- Contract Tests: Validate API compliance
- Structure Tests: Verify SDK interface correctness
- Pagination Tests: Handle paginated endpoints
- Mock Scenarios: Support offline development
The language! macro is a Rust declarative macro that expands into a complete LanguageGenerator implementation. This approach provides several benefits:
- Zero Boilerplate: Developers define behavior, not implementation
- Compile-Time Validation: Errors caught during compilation, not runtime
- Consistent Architecture: All generators follow the same patterns
- Easy Maintenance: Changes to the macro system benefit all languages
The casing system automatically handles the complexities of cross-language naming:
// Input: "getUserProfile" (from OpenAPI)
// Outputs:
// Python: get_user_profile (method), GetUserProfile (class)
// Java: getUserProfile (method), GetUserProfile (class)
// C#: GetUserProfile (method), GetUserProfile (class)The system understands various input formats:
- camelCase (
getUserId) - PascalCase (
GetUserId) - snake_case (
get_user_id) - kebab-case (
get-user-id)
And converts them to any target convention with proper word boundary detection.
The system uses strongly-typed data structures that bridge the gap between OpenAPI specifications and target language requirements:
pub struct OperationInfo {
pub class_name: String, // GetUserProfile
pub method_name: String, // get_user_profile
pub method: String, // GET
pub path: String, // /users/{id}/profile
pub parameters: Option<Vec<ParameterInfo>>,
pub request_body: Option<RequestBody>,
pub responses: HashMap<StatusCode, Response>,
}
pub struct ParameterInfo {
pub original_name: String, // userId (from OpenAPI)
pub variable_name: String, // user_id (language-specific)
pub location: String, // path, query, header
pub required: bool,
pub param_type: String,
pub description: Option<String>,
}Templates receive rich, pre-processed contexts that eliminate the need for complex template logic:
{% for operation in operations %}
class {{ operation.class_name }}:
def {{ operation.method_name }}(self,
{% for param in operation.parameters %}
{{ param.variable_name }}: {{ param.param_type }},
{% endfor %}
):
# Implementation
{% endfor %}- Parse OpenAPI specification into strongly-typed structures
- Resolve all
$refreferences lazily as needed - Extract operations, grouping by tags for modular organization
- Analyze parameters, request/response schemas, and security requirements
- Apply naming conventions based on language configuration
- Transform OpenAPI operations into language-specific data models
- Generate test specifications with proper parameter casing
- Create rich context objects for template rendering
- Render main SDK files (clients, models)
- Generate comprehensive test suites
- Create package configuration files
- Apply language-specific formatting and structure
- Create appropriate directory structures
- Write all generated files to target locations
- Ensure proper file permissions and encoding
- Generate package metadata and documentation
Creating support for a new language requires only:
- Language Configuration: Define the
language!macro call - Template Creation: Write Jinja2 templates for the target language
- Language-Specific Filters: Add any custom template filters needed
Example for adding Rust SDK generation:
language! {
name: Rust,
filters: [rust_type, snake_case, pascal_case],
class_casing: Casing::Pascal,
operation_casing: Casing::Snake,
import_casing: Casing::Snake,
variable_casing: Casing::Snake,
render: [
multiple {
render "models" => "src/{}/models.rs",
render "client" => "src/{}/client.rs",
},
render "lib" => "src/lib.rs",
render "cargo_toml" => "Cargo.toml"
],
tests: [
multiple {
render "tests" => "tests/{}/mod.rs",
}
]
}Templates have access to powerful features:
- Language-Specific Filters: Type conversion, naming conventions
- Rich Context Objects: Pre-processed data with all necessary information
- Conditional Logic: Handle optional parameters, different response types
- Iteration Support: Process collections of operations, parameters, schemas
The test generation system automatically creates:
- Contract Tests: Verify API responses match OpenAPI specifications
- Structure Tests: Ensure SDK interfaces are correctly generated
- Pagination Tests: Handle APIs with cursor or offset-based pagination
- Mock Scenarios: Support offline development with realistic test data
- xdk-openapi: OpenAPI 3.0 parser with reference resolution
- xdk-lib: Shared utilities, models, and generation logic
- xdk-gen: Language-specific generators using the
language!macro - xdk-build: CLI tool for invoking generators
- OpenAPI specification parsed into typed structures
- Operations extracted and grouped by tags
- Language-specific naming conventions applied
- Templates rendered with processed contexts
- Files written to output directory structure