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
@ObjectSchemafor each nested type - ✅ Full type preservation -
SafetySetting[]notRecord<string, any>[] - ✅ Schema references -
@PortObject({ schema: HttpOptions }) - ✅ Array references -
@PortArray({ itemConfig: { schema: Part } }) - ✅ TypeScript parsing - Parses
.d.tsfiles 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
AbortSignaland 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
pnpm add -D @badaitech/chaingraph-codegenQuick Start
Generate Schema from External SDK
chaingraph-codegen generate \
--library @google/genai \
--type GenerateContentConfig \
--mode class \
--output ./generated/gemini-config.tsExample Output
Input: GenerateContentConfig from @google/genai
Output: 2,435 lines with 62 separate @ObjectSchema classes:
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
# 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.tsOptions
| Option | Description | Example |
|---|---|---|
--library | NPM package name | @google/genai |
--type | Type/Interface name | GenerateContentConfig |
--mode | Output mode | class (default) or config |
--output | Output file path | ./generated/config.ts |
--exclude | Fields to exclude | httpOptions abortSignal |
Development
Setup
# Install dependencies
pnpm install
# Build
pnpm build
# Run tests
pnpm test
# Type check
pnpm type-check
# Watch mode (development)
pnpm devTest Coverage
36 tests across 10 test files - 100% passing ✅
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 logicProject 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 APIDocumentation
- CHECKPOINT.md - Current status and achievements
- NEXT_STEPS.md - Remaining work and roadmap
- ARCHITECTURE.md - System architecture
- IMPLEMENTATION_PLAN_V2.md - Detailed implementation plan
Examples
See examples/ directory for:
gemini-config.example.ts- Example configuration fileEXAMPLE_OUTPUT.md- Before/after comparisons
Testing with Real SDK
Current test validates parsing of real Gemini SDK:
// 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 typesKnown Limitations
Complex unions → @PortAny - Union types like
Content | string | Part[]map toany- Examples:
ContentUnion,PartUnion - Future: Add custom type mappers for specific patterns
- Examples:
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.