Project 8: api-forge
Build a CLI that generates API clients or server stubs from schemas.
Quick Reference
| Attribute | Value |
|---|---|
| Difficulty | Level 3 (Advanced) |
| Time Estimate | 2 weeks |
| Language | Rust (Alternatives: Go, Python) |
| Prerequisites | CLI basics, HTTP, JSON/YAML |
| Key Topics | Schema parsing, code generation, templates |
1. Learning Objectives
By completing this project, you will:
- Parse and validate OpenAPI-like schemas.
- Build a code generation pipeline from schema to files.
- Handle local and remote schema sources safely.
- Produce deterministic output that is stable across runs.
- Design template-based generation for extensibility.
2. Theoretical Foundation
2.1 Core Concepts
- Schemas: OpenAPI defines endpoints, methods, parameters, and responses. Your generator reads a subset.
- Validation: Without validation, code generation emits invalid or incomplete output.
- Code Generation: Structured templates produce consistent output with predictable naming.
- Determinism: Generated code must be stable to avoid unnecessary diffs.
2.2 Why This Matters
Schema-driven tooling powers SDKs, docs, and mocks. Building a generator teaches you to map abstract definitions into concrete code artifacts.
2.3 Historical Context / Background
Swagger/OpenAPI popularized schema-first design. Tools like openapi-generator and swagger-codegen automate client SDK creation; your tool recreates core mechanics.
2.4 Common Misconceptions
- “Parsing YAML is enough”: You must validate structure and required fields.
- “Generation is trivial”: Naming conventions, imports, and types are complex.
3. Project Specification
3.1 What You Will Build
A CLI named api-forge that can:
- Load a schema from file or URL
- Validate required schema fields
- Generate client stubs for a chosen language
- Emit JSON metadata for tooling
3.2 Functional Requirements
- Schema input:
--schemasupports file path or URL. - Validation: Check required sections (
paths,components). - Generation: Output client stubs in chosen language.
- Output modes: Table log or JSON summary.
3.3 Non-Functional Requirements
- Determinism: Same schema yields same output order.
- Safety: Do not overwrite existing output without
--force. - Performance: Handle schemas with 100+ endpoints.
3.4 Example Usage / Output
$ api-forge generate --schema openapi.yaml --lang go --out ./client
Generated client/client.go
Generated client/models.go
3.5 Real World Outcome
After generation, the output directory contains:
client.gowith a typed API clientmodels.gowith request/response structsREADME.mddocumenting usage
You can then import the client in an app and call endpoints with structured types.
4. Solution Architecture
4.1 High-Level Design
+-------------+ +-----------------+ +------------------+
| Schema Load | --> | Validator | --> | Generator |
+-------------+ +-----------------+ +------------------+
| | |
+-------------------+--------------------+
Templates
4.2 Key Components
| Component | Responsibility | Key Decisions |
|---|---|---|
| Loader | Fetch schema | URL vs file |
| Validator | Check required fields | fail-fast vs warnings |
| Model | Normalize schema | naming rules |
| Generator | Render templates | template engine |
4.3 Data Structures
struct Endpoint {
method: String,
path: String,
request_type: Option<String>,
response_type: Option<String>,
}
4.4 Algorithm Overview
Key Algorithm: Schema -> code
- Load schema (file or URL).
- Validate required fields and normalize types.
- Build internal model of endpoints.
- Render templates into output files.
Complexity Analysis:
- Time: O(E) for E endpoints
- Space: O(E) for model storage
5. Implementation Guide
5.1 Development Environment Setup
cargo new api-forge
cargo add clap reqwest serde_yaml tera
5.2 Project Structure
api-forge/
├── src/
│ ├── main.rs
│ ├── load.rs
│ ├── validate.rs
│ ├── model.rs
│ └── generate.rs
├── templates/
│ ├── client.rs.tmpl
│ └── models.rs.tmpl
└── README.md
5.3 The Core Question You Are Answering
“How do I transform abstract API definitions into stable, usable code artifacts?”
5.4 Concepts You Must Understand First
- OpenAPI schema basics
- HTTP method semantics
- Template rendering
- Naming and type mapping
5.5 Questions to Guide Your Design
- How will you map schema types to language types?
- How do you ensure deterministic ordering of endpoints?
- Should generation overwrite existing files?
5.6 Thinking Exercise
Given a simple schema with two endpoints, manually sketch the generated client functions and types.
5.7 The Interview Questions They Will Ask
- Why is deterministic output important in generators?
- How do you validate schema correctness?
- What are the tradeoffs of template-based generation?
5.8 Hints in Layers
Hint 1: Start with a tiny schema and one endpoint.
Hint 2: Generate a single file first, then split into models and client.
Hint 3: Add sorting by path/method to keep output stable.
5.9 Books That Will Help
| Topic | Book | Chapter |
|---|---|---|
| Web APIs | “Design and Build Great Web APIs” | Ch. 3 |
| Data modeling | “Designing Data-Intensive Applications” | Ch. 4 |
5.10 Implementation Phases
Phase 1: Foundation (3-4 days)
Goals:
- Schema loading
- Basic validation
Checkpoint: Schema errors are detected.
Phase 2: Generation (5-6 days)
Goals:
- Internal model
- Template rendering
Checkpoint: Client stubs generated.
Phase 3: Polish (2-3 days)
Goals:
- JSON output mode
- Deterministic ordering
Checkpoint: Re-running produces identical output.
6. Testing Strategy
6.1 Test Categories
| Category | Purpose | Examples |
|---|---|---|
| Unit Tests | Validator | missing fields |
| Integration Tests | End-to-end | schema -> files |
| Edge Cases | Large schema | 100+ endpoints |
6.2 Critical Test Cases
- Missing
pathsshould error. - Endpoint with unknown type should warn or map to string.
- Output is deterministic across runs.
7. Common Pitfalls and Debugging
| Pitfall | Symptom | Solution |
|---|---|---|
| Non-deterministic output | Flaky diffs | Sort endpoints |
| Weak validation | Broken code | Enforce required fields |
| Overwriting files | Data loss | Require --force |
8. Extensions and Challenges
8.1 Beginner Extensions
- Add
--dry-runmode - Add
--list-endpoints
8.2 Intermediate Extensions
- Add docs generator
- Add mock server stubs
8.3 Advanced Extensions
- Add multiple language targets
- Add plugin-based templates
9. Real-World Connections
- SDK generation in API platforms
- CI pipeline validation of schemas
10. Resources
- OpenAPI spec
openapi-generatorsource for ideas
11. Self-Assessment Checklist
- I can explain schema validation
- I can keep generated output deterministic
12. Submission / Completion Criteria
Minimum Viable Completion:
- Validate schema and generate basic stub
Full Completion:
- Deterministic output + JSON summary
Excellence (Going Above and Beyond):
- Multiple language targets and plugin templates