- Handle type arrays: type: ['string', 'null'] → string | null - Handle const keyword: const: "active" → 'active' literal type - Handle nullable (OpenAPI 3.0 backward compatibility) - Extract and display webhook count in metadata - Add security escaping for string literals and JSDoc comments - Add OpenAPI 3.1 test fixture and 12 unit tests Fixes #365 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
137 lines
4.9 KiB
Markdown
137 lines
4.9 KiB
Markdown
---
|
|
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' : ...`
|