# 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; async apiV1BuildsIdGet(requestParameters: ApiV1BuildsIdGetRequest): Promise; async apiV1BuildsIdDelete(requestParameters: ApiV1BuildsIdDeleteRequest): Promise; async apiV1PartitionsRefStatusGet(requestParameters: ApiV1PartitionsRefStatusGetRequest): Promise; async apiV1PartitionsRefEventsGet(requestParameters: ApiV1PartitionsRefEventsGetRequest): Promise; async apiV1AnalyzePost(requestParameters: ApiV1AnalyzePostRequest): Promise; } // 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 ) -> Result, ...> { // 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` 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