160 lines
No EOL
6.6 KiB
Markdown
160 lines
No EOL
6.6 KiB
Markdown
# Chunk 1: TypeScript Client Generation
|
|
|
|
**Parent:** [Build Graph Dashboard](../build-graph-dashboard.md)
|
|
**Next:** [Chunk 2: Hello World App](./chunk-2-hello-world-app.md)
|
|
|
|
## Overview
|
|
|
|
Generate TypeScript client code from the DataBuild Build Graph Service OpenAPI specification to provide type-safe API access for the dashboard.
|
|
|
|
## Scope
|
|
|
|
### In Scope
|
|
- Generate OpenAPI specification from Build Graph Service using aide
|
|
- Create typed TypeScript client from OpenAPI spec using OpenAPI Generator
|
|
- Set up Bazel rules for OpenAPI-to-TypeScript generation
|
|
- Implement path parameter structs for proper aide OpenAPI generation
|
|
- CLI-based OpenAPI spec extraction
|
|
|
|
### Out of Scope
|
|
- HTTP-based spec extraction (use CLI flag instead)
|
|
- External Bazel modules (use OpenAPI Generator JAR directly)
|
|
- Custom operation IDs (use auto-generated method names)
|
|
- Client-side validation (rely on server-side validation)
|
|
|
|
## Technical Approach
|
|
|
|
### OpenAPI-Based Generation
|
|
Generate TypeScript client from OpenAPI specification automatically derived from Build Graph Service:
|
|
|
|
Key API endpoints to generate TypeScript client for:
|
|
- `POST /api/v1/builds` - Submit build request
|
|
- `GET /api/v1/builds/:id` - Get build status
|
|
- `DELETE /api/v1/builds/:id` - Cancel build request
|
|
- `GET /api/v1/partitions/:ref/status` - Get partition status
|
|
- `GET /api/v1/partitions/:ref/events` - Get partition events
|
|
- `POST /api/v1/analyze` - Analyze build graph
|
|
|
|
### Generated Client Structure
|
|
```typescript
|
|
// Generated types from OpenAPI spec (auto-generated models)
|
|
export * from './AnalyzeRequest';
|
|
export * from './BuildRequest';
|
|
export * from './BuildStatusResponse';
|
|
export * from './PartitionStatusResponse';
|
|
// ... all other model types
|
|
|
|
// Generated client API with auto-generated method names
|
|
export class DefaultApi {
|
|
constructor(configuration?: Configuration);
|
|
|
|
// Auto-generated method names from OpenAPI paths
|
|
async apiV1BuildsPost(requestParameters: ApiV1BuildsPostRequest): Promise<BuildRequestResponse>;
|
|
async apiV1BuildsIdGet(requestParameters: ApiV1BuildsIdGetRequest): Promise<BuildStatusResponse>;
|
|
async apiV1BuildsIdDelete(requestParameters: ApiV1BuildsIdDeleteRequest): Promise<any>;
|
|
async apiV1PartitionsRefStatusGet(requestParameters: ApiV1PartitionsRefStatusGetRequest): Promise<PartitionStatusResponse>;
|
|
async apiV1PartitionsRefEventsGet(requestParameters: ApiV1PartitionsRefEventsGetRequest): Promise<PartitionEventsResponse>;
|
|
async apiV1AnalyzePost(requestParameters: ApiV1AnalyzePostRequest): Promise<AnalyzeResponse>;
|
|
}
|
|
|
|
// Type-safe request parameter interfaces
|
|
export interface ApiV1BuildsPostRequest {
|
|
buildRequest: BuildRequest;
|
|
}
|
|
|
|
export interface ApiV1BuildsIdGetRequest {
|
|
id: string;
|
|
}
|
|
```
|
|
|
|
### Bazel Integration
|
|
- Create `//databuild/client:typescript` target
|
|
- Extract OpenAPI spec using CLI flag `--print-openapi-spec`
|
|
- Use OpenAPI Generator JAR to create TypeScript client
|
|
- Ensure hermetic build process with JAR download
|
|
- Output client code to `databuild/client/typescript_generated/`
|
|
|
|
### Path Parameter Requirements
|
|
For aide to properly generate OpenAPI path parameters, all path parameters must be wrapped in structs:
|
|
|
|
```rust
|
|
#[derive(Deserialize, JsonSchema)]
|
|
pub struct BuildStatusRequest {
|
|
pub id: String,
|
|
}
|
|
|
|
pub async fn get_build_status(
|
|
Path(request): Path<BuildStatusRequest>
|
|
) -> Result<Json<BuildStatusResponse>, ...> {
|
|
// Use request.id instead of direct string
|
|
}
|
|
```
|
|
|
|
## Implementation Strategy
|
|
|
|
1. **✅ Add OpenAPI Generation to Service**
|
|
- ✅ Add `aide` dependency for OpenAPI spec generation
|
|
- ✅ Modify Axum service to use `aide::ApiRouter`
|
|
- ✅ Add JsonSchema derives to request/response types
|
|
- ✅ Add path parameter structs for proper aide integration
|
|
- ✅ Create CLI flag `--print-openapi-spec` for spec generation
|
|
|
|
2. **✅ OpenAPI Spec Extraction**
|
|
- ✅ Create Bazel rule using CLI flag instead of HTTP endpoint
|
|
- ✅ Extract spec using `build_graph_service --print-openapi-spec`
|
|
- ✅ Save spec as build artifact (JSON)
|
|
|
|
3. **✅ TypeScript Client Generation**
|
|
- ✅ Use OpenAPI Generator JAR directly (not Bazel module)
|
|
- ✅ Create Bazel rule to generate TypeScript client from spec
|
|
- ✅ Use `typescript-fetch` generator for modern fetch-based client
|
|
- ✅ Configure with camelCase naming and single request parameters
|
|
|
|
4. **✅ Bazel Rules**
|
|
- ✅ Create `//databuild/client:typescript_client` target
|
|
- ✅ Generate client code during build with proper file copying
|
|
- ✅ Ensure hermetic build with JAR download
|
|
|
|
## Deliverables
|
|
|
|
- [x] OpenAPI spec generation from Build Graph Service via CLI flag
|
|
- [x] TypeScript interfaces for all API request/response types (auto-generated)
|
|
- [x] Typed HTTP client for Build Graph Service endpoints with fetch API
|
|
- [x] Bazel rules for automated client generation using OpenAPI Generator JAR
|
|
- [x] Path parameter struct implementation for aide compatibility
|
|
|
|
## Success Criteria
|
|
|
|
- ✅ OpenAPI spec accurately reflects all service endpoints with proper path parameters
|
|
- ✅ Generated TypeScript compiles without errors using `typescript-fetch` generator
|
|
- ✅ Client provides type safety for all API endpoints with auto-generated method names
|
|
- ✅ Bazel build integrates seamlessly and generates client automatically
|
|
- ✅ Path parameter structs enable proper aide OpenAPI generation
|
|
- ✅ Ready for use in Chunk 2 (Hello World App)
|
|
|
|
## Testing
|
|
|
|
- ✅ Verify OpenAPI spec generation from service using CLI flag
|
|
- ✅ Verify generated TypeScript compiles without errors
|
|
- ✅ Validate OpenAPI spec passes OpenAPI Generator validation
|
|
- ✅ Ensure build process is hermetic and reproducible with JAR download
|
|
- ✅ Verify all API endpoints generate proper TypeScript method signatures
|
|
- ✅ Confirm path parameters are properly typed in generated client
|
|
|
|
## Implementation Notes
|
|
|
|
### Lessons Learned
|
|
|
|
1. **aide Path Parameter Requirements**: aide requires path parameters to be wrapped in structs with `JsonSchema` derives, not simple `Path<String>` extractors.
|
|
|
|
2. **OpenAPI Generator Bazel Integration**: The official Bazel module was not available in registry, so we used the JAR directly via genrule for better reliability.
|
|
|
|
3. **CLI vs HTTP Extraction**: Using a CLI flag for spec extraction is simpler and more reliable than starting an HTTP server.
|
|
|
|
4. **Auto-generated Method Names**: Without custom operationIds, OpenAPI Generator creates method names like `apiV1BuildsPost`. This can be improved in future iterations.
|
|
|
|
### Build Targets
|
|
|
|
- `//databuild/client:extract_openapi_spec` - Extracts OpenAPI spec JSON
|
|
- `//databuild/client:typescript_client` - Generates TypeScript client
|
|
- `//databuild/client:typescript` - Main target for consuming the client |