Skip to content

ChainGraph API Documentation / @badaitech/chaingraph-codegen

@badaitech/chaingraph-codegen ​

Status: ✅ Production Ready - Multi-schema generation complete

Automatic ChainGraph schema generator from TypeScript type definitions.

Overview ​

This tool parses external TypeScript libraries (like @google/genai, @anthropic-ai/sdk) and automatically generates ChainGraph node schemas with decorators, eliminating manual type recreation.

Problem it solves: When integrating external SDKs, you must manually recreate every type with ChainGraph decorators - often 100-300 lines of repetitive, error-prone code. This tool automates that entirely.

Features ​

✅ Core Capabilities ​

  • ✅ Multi-schema generation - Separate @ObjectSchema for each nested type
  • ✅ Full type preservation - SafetySetting[] not Record<string, any>[]
  • ✅ Schema references - @PortObject({ schema: HttpOptions })
  • ✅ Array references - @PortArray({ itemConfig: { schema: Part } })
  • ✅ TypeScript parsing - Parses .d.ts files from node_modules (supports pnpm)
  • ✅ JSDoc extraction - Preserves comments and descriptions
  • ✅ Dependency discovery - Recursively finds 60+ nested types
  • ✅ Self-reference handling - Handles recursive types elegantly
  • ✅ Built-in filtering - Skips AbortSignal and other browser types
  • ✅ Type mapping - Primitives, arrays, enums, objects, unions
  • ✅ Title formatting - HARM_CATEGORY_HATE_SPEECH → Harm Category Hate Speech
  • ✅ Type-safe - Zero field duplication, proper wrapper pattern

Installation ​

bash
pnpm add -D @badaitech/chaingraph-codegen

Quick Start ​

Generate Schema from External SDK ​

bash
chaingraph-codegen generate \
  --library @google/genai \
  --type GenerateContentConfig \
  --mode class \
  --output ./generated/gemini-config.ts

Example Output ​

Input: GenerateContentConfig from @google/genai

Output: 2,435 lines with 62 separate @ObjectSchema classes:

typescript
import { ObjectSchema, PortObject, PortArray, PortNumber, PortString, PortEnum } from '@badaitech/chaingraph-types'

// ==========================================
// OBJECT SCHEMAS
// ==========================================

/** HTTP options to be used in each of the requests. */
@ObjectSchema({
  description: 'HTTP options to be used in each of the requests.',
  type: 'HttpOptions',
})
export class HttpOptions {
  @PortString({ title: 'Base Url' })
  baseUrl?: string

  @PortString({ title: 'Api Version' })
  apiVersion?: string
}

/** Safety settings. */
@ObjectSchema({
  description: 'Safety settings.',
  type: 'SafetySetting',
})
export class SafetySetting {
  @PortEnum({
    title: 'Category',
    defaultValue: 'HARM_CATEGORY_UNSPECIFIED',
    options: [/* ... */]
  })
  category?: string

  @PortEnum({ title: 'Threshold', /* ... */ })
  threshold?: string
}

/** Main configuration */
@ObjectSchema({
  description: 'Optional model configuration parameters.',
  type: 'GenerateContentConfig',
})
export class GenerateContentConfig {
  /** HTTP request options */
  @PortObject({
    title: 'Http Options',
    description: 'Used to override HTTP request options.',
    schema: HttpOptions,  // ✅ Schema reference!
  })
  httpOptions?: HttpOptions  // ✅ Fully typed!

  /** Safety settings for content filtering */
  @PortArray({
    title: 'Safety Settings',
    defaultValue: [],
    itemConfig: {
      type: 'object',
      schema: SafetySetting,  // ✅ Schema reference!
    },
    isMutable: true,
  })
  safetySettings?: SafetySetting[]  // ✅ Fully typed array!

  @PortNumber({ title: 'Temperature' })
  temperature?: number
}

CLI Reference ​

Commands ​

bash
# Generate single schema
chaingraph-codegen generate \
  --library <npm-package> \
  --type <TypeName> \
  --mode <class|config> \
  --output <path>

# Exclude fields
chaingraph-codegen generate \
  --library @google/genai \
  --type GenerateContentConfig \
  --exclude httpOptions abortSignal \
  --output ./gen/config.ts

Options ​

OptionDescriptionExample
--libraryNPM package name@google/genai
--typeType/Interface nameGenerateContentConfig
--modeOutput modeclass (default) or config
--outputOutput file path./generated/config.ts
--excludeFields to excludehttpOptions abortSignal

Development ​

Setup ​

bash
# Install dependencies
pnpm install

# Build
pnpm build

# Run tests
pnpm test

# Type check
pnpm type-check

# Watch mode (development)
pnpm dev

Test Coverage ​

36 tests across 10 test files - 100% passing ✅

bash
pnpm test                        # All tests
pnpm test multi-schema-generation # Multi-schema generation
pnpm test gemini-dependencies     # Dependency discovery
pnpm test enum-generation         # Enum generation
pnpm test type-mapper             # Type mapping logic

Project Structure ​

src/
├── core/
│   ├── CodeGenerator.ts          # Main orchestrator
│   ├── TypeMapper.ts             # TS → ChainGraph mapping
│   ├── TypeDependencyCollector.ts # Nested type discovery
│   ├── SchemaRegistry.ts         # Topological sorting
│   ├── JSDocParser.ts            # Extract comments
│   ├── TemplateEngine.ts         # Code generation
│   └── types.ts                  # Type definitions
├── __tests__/                    # Test suite
├── cli.ts                        # CLI entry point
└── index.ts                      # Public API

Documentation ​

Examples ​

See examples/ directory for:

  • gemini-config.example.ts - Example configuration file
  • EXAMPLE_OUTPUT.md - Before/after comparisons

Testing with Real SDK ​

Current test validates parsing of real Gemini SDK:

text
// Discovers 55 types including:
- GenerateContentConfig (interface) - 31 properties
- SafetySetting (interface) - 3 properties
- HarmCategory (enum) - 10 values
- HarmBlockMethod (enum) - 3 values
- HttpOptions (interface) - multiple properties
// ... and 50 more types

Known Limitations ​

  1. Complex unions → @PortAny - Union types like Content | string | Part[] map to any

    • Examples: ContentUnion, PartUnion
    • Future: Add custom type mappers for specific patterns
  2. Type aliases skipped - Only interfaces and enums generate schemas

    • Type aliases are discovered but not generated
    • Future: Add type alias support

Roadmap ​

Phase 1: Foundation ✅ Complete ​

  • [x] TypeScript AST parsing with ts-morph
  • [x] Type discovery and dependency tracking
  • [x] Basic type mapping (primitives, arrays, enums)
  • [x] Test coverage (30 tests)

Phase 2: Multi-Schema Generation ✅ Complete ​

  • [x] Separate @ObjectSchema for each nested type
  • [x] Schema references (@PortObject with schema)
  • [x] Array schema references (@PortArray with itemConfig.schema)
  • [x] Full type preservation (SafetySetting[] not any[])
  • [x] Dependency-ordered output (topological sort)
  • [x] Self-reference handling (Schema.items, Schema.anyOf)
  • [x] Built-in type filtering (AbortSignal, Date, etc.)
  • [x] Integration tests (36 tests total)

Phase 3: Advanced Features 📅 Next ​

  • [ ] Union type handling (ContentUnion → specific types)
  • [ ] Type alias generation
  • [ ] Native enum support (@PortEnumFromNative with real enums)
  • [ ] Custom type mappers API
  • [ ] Multi-file output mode
  • [ ] Performance optimization

Phase 4: Production Polish 📅 Future ​

  • [ ] Publish to npm
  • [ ] CI/CD integration
  • [ ] Watch mode enhancements
  • [ ] Batch generation improvements
  • [ ] Documentation site

Contributing ​

This is an internal BadLabs tool. For questions or issues, contact the ChainGraph team.

License ​

Business Source License 1.1 (BUSL-1.1)


Note: This tool is under active development. The API may change before the 1.0 release.

Classes ​

Interfaces ​

Functions ​

Licensed under BUSL-1.1