Skip to content

Next Steps for ChainGraph Code Generator

Last Updated: 2025-10-15 Current Status: Phase 2 Complete - Multi-schema generation working Next Phase: Advanced union handling and type alias support


✅ What's Been Completed

Phase 1: Foundation

  • [x] TypeScript AST parsing
  • [x] Type mapping
  • [x] Dependency discovery
  • [x] Basic test coverage

Phase 2: Multi-Schema Generation

  • [x] Separate @ObjectSchema for each nested type
  • [x] Schema references (@PortObject, @PortArray)
  • [x] Full type preservation
  • [x] Topological sorting
  • [x] Self-reference handling
  • [x] Built-in type filtering

🎯 Phase 3: Advanced Type Handling (Next)

1. Union Type Support (High Priority)

Problem: Complex unions currently map to @PortAny

Examples:

typescript
// Gemini SDK
type ContentUnion = Content | PartUnion[] | PartUnion
type PartUnion = Part | string

// Currently generates:
@PortAny({ title: 'System Instruction' })
systemInstruction?: any  // ❌ Lost type information

Solution: Add union flattening logic

typescript
// Option 1: Pick primary type
type ContentUnion = Content | PartUnion[] | PartUnion
Use Content (the object type)
→ @PortObject({ schema: Content })

// Option 2: Generate union wrapper
@ObjectSchema({ type: 'ContentUnion' })
class ContentUnion {
  @PortObject({ schema: Content })
  content?: Content

  @PortArray({ itemConfig: { schema: Part } })
  parts?: Part[]

  @PortString()
  text?: string
}

Implementation:

  • File: src/core/TypeMapper.ts
  • Method: mapUnion() - Add logic to detect union patterns
  • Estimated time: 2-3 hours

2. Type Alias Generation (Medium Priority)

Problem: Type aliases are discovered but not generated

Example:

typescript
// Gemini SDK
export type ContentUnion = Content | PartUnion[] | PartUnion

// Currently: Skipped
// Future: Generate wrapper or select primary type

Implementation:

  • File: src/core/TemplateEngine.ts
  • Add: generateTypeAlias() method
  • Estimated time: 2 hours

3. Native Enum Support (Medium Priority)

Problem: Gemini uses string literal unions, not TypeScript enums

Current:

typescript
// Gemini SDK uses:
type HarmCategory = 'HARM_CATEGORY_HATE_SPEECH' | 'HARM_CATEGORY_HARASSMENT'

// Generates:
@PortEnum({
  options: [
    { id: 'HARM_CATEGORY_HATE_SPEECH', type: 'string', ... },
  ]
})
category?: string

Future (when SDK has real enums):

typescript
// If SDK had:
enum HarmCategory {
  HARM_CATEGORY_HATE_SPEECH = "...",
}

// Generate:
export enum HarmCategory { /* ... */ }

@PortEnumFromNative(HarmCategory, { /* ... */ })
category?: HarmCategory

Implementation:

  • Already supported! Just needs SDKs to use real enums
  • No changes needed

4. Custom Type Mappers API (Low Priority)

Goal: Allow users to override type mapping for specific types

Example:

typescript
const generator = new CodeGenerator({
  library: '@google/genai',
  typeName: 'GenerateContentConfig',
  customTypeMappers: {
    'ContentUnion': (type) => ({
      config: {
        type: 'object',
        schema: Content,  // Always use Content
      },
      metadata: {
        typeRef: 'Content',
      },
    }),
  },
})

Implementation:

  • Already has basic support in TypeMapper constructor
  • Needs documentation and examples
  • Estimated time: 1 hour

🔧 Improvements & Polish

1. CLI Enhancements

Add options:

bash
--max-depth <number>      # Control dependency discovery depth (default: 10)
--skip-built-ins          # Skip browser/Node types (default: true)
--output-mode <mode>      # single-file | multi-file (future)

2. Better Error Messages

Current:

Error: Type "Foo" not found in @bar/baz

Future:

Error: Type "Foo" not found in @bar/baz

Suggestions:
  - Did you mean "FooBar"? (similar name found)
  - Available types: Bar, Baz, FooBar, Qux
  - Check type is exported from main .d.ts file

3. Performance Optimization

Current: ~10 seconds for 62 types

Optimizations:

  • Parallel schema generation
  • Caching parsed .d.ts files
  • Incremental generation

Target: <5 seconds for 100+ types


📊 Success Metrics

Current State

  • ✅ 36/36 tests passing
  • ✅ 62 schemas generated from GenerateContentConfig
  • ✅ 2,435 lines of output
  • ✅ Zero TypeScript errors
  • ✅ Full type preservation

Phase 3 Goals

  • [ ] Handle 90% of union types correctly
  • [ ] Generate type aliases
  • [ ] <5 second generation time
  • [ ] 50+ tests covering edge cases
  • [ ] Documentation with real-world examples

🎓 For the Next Developer

If implementing union handling:

  1. Study the patterns:

    bash
    # Find all union usages in Gemini SDK
    grep "type.*=.*|" node_modules/@google/genai/dist/genai.d.ts
  2. Understand current behavior:

    • Read: src/core/TypeMapper.ts lines 159-231 (mapUnion)
    • See how literal unions become enums
    • See how complex unions become @PortAny
  3. Add union flattening:

    • Detect pattern: A | B | C where A is primary object type
    • Use A as the schema type
    • Document that B and C are ignored
  4. Test with real SDK:

    typescript
    // Test that ContentUnion generates correctly
    const code = await generator.generateMultiSchema()
    expect(code).toContain('@PortObject({ schema: Content })')

If implementing type aliases:

  1. Extend TemplateEngine:

    • Add generateTypeAlias() method
    • Decision: Generate as wrapper class or select primary type?
  2. Update CodeGenerator:

    • Handle metadata.kind === 'type-alias'
    • Currently skipped in generateMultiSchema()
  3. Add tests:

    • Create type-alias-generation.test.ts
    • Test simple aliases: type Foo = Bar
    • Test union aliases: type Foo = A | B

🔗 Resources

Documentation

  • README.md - Project overview
  • CHECKPOINT.md - Current state
  • ARCHITECTURE.md - System design
  • IMPLEMENTATION_PLAN_V2.md - Detailed implementation guide

Key Files

  • src/core/CodeGenerator.ts:104 - generateMultiSchema() method
  • src/core/TypeMapper.ts:159 - mapUnion() method
  • src/core/TemplateEngine.ts:495 - generateObjectSchema() method

Tests

  • src/tests/multi-schema-generation.test.ts - Multi-schema tests
  • src/tests/gemini-dependencies.test.ts - Dependency discovery

Ready for Phase 3! Start with union type handling for maximum impact.

Licensed under BUSL-1.1