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_SPEECHHarm 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