swagger-tools/docs/tasks/archive/openapi-31-support-task.md
rimskij 58c91615b9 feat: add OpenAPI 3.1 TypeScript generation support
- 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>
2026-01-12 21:20:13 +01:00

4.9 KiB

openproject
365

Task: OpenAPI 3.1 TypeScript Generation Support

  • Analysis: docs/analysis/feature-enhancements-analysis.md (Feature 2)
  • OpenProject: #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

  • Code implemented per specification
  • TypeScript compilation CLEAN
  • Lint checks PASSED (no lint script configured)
  • ALL tests passing (12/12)
  • Manual verification completed
  • 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:
    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:
    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:
    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' : ...