--- openproject: 365 --- # Task: OpenAPI 3.1 TypeScript Generation Support ## Related Documents - Analysis: `docs/analysis/feature-enhancements-analysis.md` (Feature 2) - OpenProject: [#365](https://pm.hyperlocalplatform.com/work_packages/365) - Branch: `feature/365-openapi-31-support` (from `dev`) ## Priority NORMAL ## Objective Enhance TypeScript generation to properly handle OpenAPI 3.1-specific JSON Schema features. While parsing already works via swagger-parser, the `generate-types` tool doesn't handle 3.1's array types, `const` keyword, or webhook extraction. ## Definition of Done - [x] Code implemented per specification - [x] TypeScript compilation CLEAN - [x] Lint checks PASSED (no lint script configured) - [x] ALL tests passing (12/12) - [x] Manual verification completed - [x] PROOF PROVIDED ## Scope ### IN SCOPE - Handle `type` as array: `type: ['string', 'null']` → `string | null` - Handle `const` keyword: `const: "value"` → literal type `'value'` - Extract `webhooks` count in metadata - Display webhook count in formatted output - Test fixture with OpenAPI 3.1 spec ### OUT OF SCOPE - Full JSON Schema 2020-12 support (only common features) - `$ref` with sibling properties (complex edge case) - `pathItems` in components (rarely used) - Batch operations (separate feature) ## Sub-Tasks ### Phase 1: Type Array Handling #### 1.1 Update schemaToType() for array types - **Details**: Detect when `type` is an array and map each type, joining with `|` - **Files**: `src/tools/generate.ts` - **Code**: ```typescript if (Array.isArray(s.type)) { return s.type.map(t => t === 'null' ? 'null' : mapPrimitiveType(t)).join(' | '); } ``` - **Testing**: Generate types from spec with `type: ['string', 'null']` #### 1.2 Handle nullable migration - **Details**: OpenAPI 3.1 replaces `nullable: true` with `type: ['T', 'null']` - **Files**: `src/tools/generate.ts` - **Testing**: Both 3.0 `nullable` and 3.1 array types produce `T | null` ### Phase 2: Const Keyword Support #### 2.1 Implement const type generation - **Details**: When `const` is present, output a literal type - **Files**: `src/tools/generate.ts` - **Code**: ```typescript if (s.const !== undefined) { return typeof s.const === 'string' ? `'${s.const}'` : String(s.const); } ``` - **Testing**: Schema with `const: "active"` generates `'active'` ### Phase 3: Webhook Metadata Extraction #### 3.1 Add webhookCount to ParsedSpec - **Details**: Add optional `webhookCount` field to ParsedSpec interface - **Files**: `src/lib/types.ts` - **Testing**: Type compiles #### 3.2 Extract webhooks in parseSpec() - **Details**: Count webhooks from `spec.webhooks` if present - **Files**: `src/lib/parser.ts` - **Code**: ```typescript webhookCount: spec.webhooks ? Object.keys(spec.webhooks).length : undefined ``` - **Testing**: Parse 3.1 spec with webhooks, verify count #### 3.3 Display webhook count in formatted output - **Details**: Show webhook count in human-readable output when present - **Files**: `src/utils/format.ts` - **Testing**: Format output includes "Webhooks: N" ### Phase 4: Testing #### 4.1 Create OpenAPI 3.1 test fixture - **Details**: Create a 3.1 spec with array types, const, and webhooks - **Files**: `test/fixtures/openapi-31.yaml` (NEW) - **Testing**: Fixture parses successfully #### 4.2 Add unit tests for 3.1 features - **Details**: Test type generation for all new features - **Files**: `scripts/self-testing/openapi-31-test.ts` (NEW) - **Testing**: All tests pass #### 4.3 Verify backward compatibility - **Details**: Ensure existing 3.0 and 2.0 specs still work - **Files**: Existing test fixtures - **Testing**: No regression in existing functionality ## Files to Modify | File | Change | |------|--------| | `src/tools/generate.ts` | Handle array types, const keyword | | `src/lib/types.ts` | Add `webhookCount?: number` to ParsedSpec | | `src/lib/parser.ts` | Extract webhook count from spec | | `src/utils/format.ts` | Display webhook count | | `test/fixtures/openapi-31.yaml` | NEW: 3.1 test fixture | | `scripts/self-testing/openapi-31-test.ts` | NEW: Unit tests | ## Risks & Mitigations | Risk | Impact | Mitigation | |------|--------|------------| | Complex array type combinations | LOW | Map each type individually, join with `\|` | | `const` with complex objects | LOW | Use JSON.stringify for non-primitives | | Breaking existing 3.0 specs | LOW | Changes are additive, test backward compat | | Type guard complexity for 3.1 detection | LOW | Use existing `isOpenAPI31()` guard | ## Testing Strategy - Build: `npm run build` - must pass - Lint: `npm run lint` - must pass - Unit tests: `npx tsx scripts/self-testing/openapi-31-test.ts` - Manual: Generate types from 3.1 spec, verify output ## Implementation Notes - The `isOpenAPI31()` type guard already exists in `src/lib/spec-guards.ts` - swagger-parser v10.1.1 already parses 3.1 specs correctly - Changes should be additive - don't break 3.0/2.0 compatibility - For const with objects, use `typeof value === 'object' ? 'object' : ...`