Unnamed Skill
Types package architecture for ChainGraph core definitions. THE foundation package for all development. Use when working on packages/chaingraph-types, port system, decorators, node classes, flow definitions, execution context, propagation, or any type-related code. Contains 9 port types, decorator system, compositional node architecture, execution engine. Triggers: types, port, decorator, @Node, @Input, @Output, @PortString, @PortArray, @PortObject, BaseNode, INode, IPort, IEdge, IFlow, ExecutionEngine, ExecutionContext, propagation.
$ Installer
git clone https://github.com/chaingraphlabs/chaingraph /tmp/chaingraph && cp -r /tmp/chaingraph/.claude/skills/types-architecture ~/.claude/skills/chaingraph// tip: Run this command in your terminal to install the skill
name: types-architecture description: Types package architecture for ChainGraph core definitions. THE foundation package for all development. Use when working on packages/chaingraph-types, port system, decorators, node classes, flow definitions, execution context, propagation, or any type-related code. Contains 9 port types, decorator system, compositional node architecture, execution engine. Triggers: types, port, decorator, @Node, @Input, @Output, @PortString, @PortArray, @PortObject, BaseNode, INode, IPort, IEdge, IFlow, ExecutionEngine, ExecutionContext, propagation.
ChainGraph Types Architecture
This skill provides comprehensive architectural guidance for the @badaitech/chaingraph-types package - THE foundation package containing all core type definitions, port system, node architecture, decorators, and execution engine.
Package Overview
Location: packages/chaingraph-types/
Purpose: Core type definitions, base implementations, and execution engine
Key Features: TypeScript decorators, compositional node architecture, 9 port types, propagation engine
Complete Directory Structure
packages/chaingraph-types/src/
โโโ index.ts # Main entry - exports everything
โโโ json-transformers.ts # SuperJSON serialization
โ
โโโ decorator/ # TypeScript decorators โญ
โ โโโ index.ts # All decorator exports
โ โโโ node.decorator.ts # @Node() decorator
โ โโโ port.decorator.ts # @Port() base decorator
โ โโโ port.decorator.types.ts # PortDecoratorOptions, ObjectPortSchemaInput
โ โโโ port-config.decorator.ts # @Input(), @Output(), @Name(), @Description()
โ โโโ port-visibility.decorator.ts # @PortVisibility() conditional visibility
โ โโโ port-update.decorator.ts # Port update tracking
โ โโโ scalar.decorator.ts # @PortString(), @PortNumber(), @PortBoolean()
โ โโโ object.decorator.ts # @PortObject()
โ โโโ array.decorator.ts # @PortArray(), @PortArrayNumber()
โ โโโ enum.decorator.ts # @PortEnum()
โ โโโ stream.decorator.ts # @PortStream()
โ โโโ secret.decorator.ts # @PortSecret()
โ โโโ object-schema.decorator.ts # Object schema definition
โ โโโ metadata-storage.ts # reflect-metadata storage
โ โโโ registry.ts # Node type registry
โ โโโ recursive-normalization.ts # Config normalization
โ
โโโ node/ # Node system โญโญ
โ โโโ index.ts # Node exports
โ โโโ interface.ts # INode interface
โ โโโ base-node.ts # BaseNode class
โ โโโ base-node-compositional.ts # Compositional implementation
โ โโโ types.ts # NodeMetadata, NodeExecutionResult
โ โโโ node-enums.ts # NodeStatus enum
โ โโโ category.ts # NodeCategory enum
โ โโโ node-ui.ts # NodeUIMetadata, Position
โ โโโ default-ports.ts # System ports (flowIn, flowOut, error)
โ โโโ traverse-ports.ts # findPort() utility
โ โโโ interfaces/ # 10+ node interfaces
โ โ โโโ inode-composite.ts # INodeComposite (combines 9 interfaces)
โ โ โโโ icore-node.ts # Core identity/status
โ โ โโโ iport-manager.ts # Port CRUD
โ โ โโโ iport-binder.ts # Port binding
โ โ โโโ icomplex-port-handler.ts # Complex type handling
โ โ โโโ inode-ui.ts # UI metadata
โ โ โโโ inode-events.ts # Event emission
โ โ โโโ iserializable.ts # Serialization
โ โ โโโ inode-versioning.ts # Version tracking
โ โ โโโ inode-clonable.ts # Cloning
โ โ โโโ i-system-port-manager.ts # System ports
โ โโโ implementations/ # Component implementations
โ โโโ port-manager.ts
โ โโโ indexed-port-manager.ts
โ โโโ port-binder.ts
โ โโโ complex-port-handler.ts
โ โโโ node-event-manager.ts
โ โโโ node-ui-manager.ts
โ โโโ node-serializer.ts
โ โโโ node-version-manager.ts
โ โโโ system-port-manager.ts
โ โโโ port-update-collector.ts
โ
โโโ port/ # Port system โญโญโญ
โ โโโ index.ts # Port exports
โ โโโ base/
โ โ โโโ IPort.ts # IPort interface (212 lines)
โ โ โโโ BasePort.ts # BasePort abstract class
โ โ โโโ types.ts # All port config types
โ โ โโโ base-config.schema.ts # Zod validation schemas
โ โ โโโ secret.ts # Secret type definitions
โ โโโ instances/ # 9 port implementations
โ โ โโโ StringPort.ts
โ โ โโโ NumberPort.ts
โ โ โโโ BooleanPort.ts
โ โ โโโ ArrayPort.ts
โ โ โโโ ObjectPort.ts
โ โ โโโ StreamPort.ts
โ โ โโโ EnumPort.ts
โ โ โโโ AnyPort.ts
โ โ โโโ SecretPort.ts
โ โโโ plugins/ # Validation/serialization plugins
โ โ โโโ PortPluginRegistry.ts
โ โ โโโ StringPortPlugin.ts
โ โ โโโ NumberPortPlugin.ts
โ โ โโโ BooleanPortPlugin.ts
โ โ โโโ ArrayPortPlugin.ts
โ โ โโโ ObjectPortPlugin.ts
โ โ โโโ StreamPortPlugin.ts
โ โ โโโ EnumPortPlugin.ts
โ โ โโโ AnyPortPlugin.ts
โ โ โโโ SecretPortPlugin.ts
โ โโโ factory/
โ โ โโโ PortFactory.ts # Port creation factory
โ โโโ transfer-rules/ # Port compatibility rules
โ โ โโโ engine.ts # TransferEngine
โ โ โโโ types.ts
โ โ โโโ predicates.ts
โ โ โโโ strategies.ts
โ โ โโโ rules/default-rules.ts
โ โโโ utils/
โ โโโ json-schema-converter.ts
โ โโโ json-schema-types.ts
โ
โโโ edge/ # Edge system
โ โโโ interface.ts # IEdge interface
โ โโโ edge.ts # Edge class
โ โโโ types.ts # EdgeStatus, EdgeMetadata, EdgeAnchor
โ โโโ events.ts # Edge events
โ
โโโ flow/ # Flow system โญโญ
โ โโโ interface.ts # IFlow interface
โ โโโ flow.ts # Flow class
โ โโโ types.ts # FlowMetadata
โ โโโ events.ts # FlowEventType (18 types)
โ โโโ execution-events.ts # ExecutionEventEnum (17 types)
โ โโโ execution-engine.ts # ExecutionEngine class
โ โโโ execution-handlers.ts # Event handlers
โ โโโ debugger.ts # FlowDebugger
โ โโโ debugger-types.ts # DebuggerState, DebuggerCommand
โ โโโ edge-transfer-service.ts # Data transfer between ports
โ โโโ cycleDetection.ts # DAG validation
โ โโโ propagation/ # Propagation engine
โ โ โโโ PropagationEngine.ts
โ โ โโโ types.ts # ActionContext, PropagationAction
โ โ โโโ actions/
โ โ โโโ TransferRulesAction.ts
โ โโโ serializer/
โ โโโ flow-serializer.ts
โ
โโโ execution/ # Execution context
โ โโโ execution-context.ts # ExecutionContext class
โ โโโ emitted-event-context.ts # Event-driven execution
โ โโโ integration-context.ts # Integration settings
โ โโโ wallet-context.ts # Wallet/crypto context
โ โโโ arch-a-i-context.ts # AI agent context
โ
โโโ utils/ # Utilities
โโโ async-queue.ts # Async queue for execution
โโโ event-queue.ts # Event queue
โโโ semaphore.ts # Concurrency control
โโโ deep-copy.ts
โโโ deep-equal.ts
Node System Architecture
Compositional Design
Nodes use a compositional architecture with 9 specialized interfaces combined into INodeComposite:
File: src/node/interfaces/inode-composite.ts
interface INodeComposite extends
ICoreNode, // Core identity and status
IPortManager, // Port CRUD operations
IPortBinder, // Port binding to node
IComplexPortHandler, // Complex type handling (Array, Object)
INodeUI, // UI metadata (position, dimensions)
INodeEvents, // Event subscription/emission
ISerializable, // Serialization
INodeVersioning, // Version tracking
ISystemPortManager, // System ports (flowIn, flowOut, error)
INodeClonable // Deep cloning
{
// Additional methods
initialize(portsConfig?: Map<string, IPortConfig>): void
executeWithSystemPorts(context: ExecutionContext): Promise<NodeExecutionResult>
startBatchUpdate(): void
commitBatchUpdate(eventContext?: EventContext): Promise<void>
}
BaseNode Implementation
File: src/node/base-node-compositional.ts
class BaseNodeCompositional implements INodeComposite {
// Core properties
protected _id: string
protected _metadata: NodeMetadata
protected _status: NodeStatus
// Specialized components (composition over inheritance)
protected portManager: PortManager
protected portBinder: PortBinder
protected complexPortHandler: ComplexPortHandler
protected eventManager: NodeEventManager
protected uiManager: NodeUIManager
protected versionManager: NodeVersionManager
protected serializer: NodeSerializer
protected systemPortManager: SystemPortManager
protected portUpdateCollector: PortUpdateCollector
// Execute method - override in subclasses
async execute(context: ExecutionContext): Promise<NodeExecutionResult> {
throw new Error('execute() must be implemented')
}
}
NodeStatus Lifecycle
File: src/node/node-enums.ts
Idle โ Initialized โ Ready โ Executing โ Completed
โ โ
Skipped Error
โ
Disposed
NodeMetadata
File: src/node/types.ts
interface NodeMetadata {
type: string // Required: Node class identifier
id?: string // Unique node ID
title?: string // Display name
category?: NodeCategory // e.g., 'math', 'flow-control', 'ai'
description?: string
version?: number
icon?: string
tags?: string[]
author?: string
parentNodeId?: string // For grouped nodes
ui?: NodeUIMetadata // Position, dimensions
flowPorts?: FlowPorts // System port configuration
}
interface FlowPorts {
flowIn: boolean // Has flow input port
flowOut: boolean // Has flow output port
error: boolean // Has error port
errorMessage: boolean // Has error message port
}
Port System (9 Types)
IPort Interface
File: src/port/base/IPort.ts (212 lines)
interface IPort<C extends IPortConfig = IPortConfig> {
// Identity
id: string
key: string
// Configuration
getConfig(): C
setConfig(newConfig: C): void
// Value management
getValue(): ExtractValue<C> | undefined
setValue(newValue: ExtractValue<C>): void
reset(): void
getDefaultValue(): ExtractValue<C> | undefined
// Validation
validate(): boolean
validateValue(value: ExtractValue<C>): boolean
validateConfig(config: C): boolean
// Serialization
serialize(): JSONValue
deserialize(data: JSONValue): IPort<C>
serializeConfig(config: C): JSONValue
serializeValue(value: ExtractValue<C>): JSONValue
deserializeConfig(data: JSONValue): C
deserializeValue(data: JSONValue): ExtractValue<C>
// Cloning
clone(): IPort<C>
cloneWithNewId(): IPort<C>
// System/Connection
isSystem(): boolean
isSystemError(): boolean
addConnection(nodeId: string, portId: string): void
removeConnection(nodeId: string, portId: string): void
}
Port Types and Configurations
File: src/port/base/types.ts
| Type | Config Interface | Key Properties |
|---|---|---|
string | StringPortConfig | defaultValue, minLength, maxLength, pattern, multiline |
number | NumberPortConfig | defaultValue, min, max, step, integer |
boolean | BooleanPortConfig | defaultValue |
array | ArrayPortConfig<Item> | itemConfig, minLength, maxLength, isMutable |
object | ObjectPortConfig<Schema> | schema, isSchemaMutable |
stream | StreamPortConfig<Value> | itemConfig (for channel items) |
enum | EnumPortConfig | options: EnumOption[] |
secret | SecretPortConfig<SecretType> | secretType |
any | AnyPortConfig | No constraints |
Port Instances
Location: src/port/instances/
Each port type has a dedicated class extending BasePort<Config>:
// StringPort.ts
class StringPort extends BasePort<StringPortConfig> {
validateValue(value: string): boolean {
const { minLength, maxLength, pattern } = this.config
// Validation logic
}
}
// ArrayPort.ts
class ArrayPort<T> extends BasePort<ArrayPortConfig<T>> {
// Handles nested item configs
// Supports mutable/immutable arrays
}
// ObjectPort.ts
class ObjectPort<S> extends BasePort<ObjectPortConfig<S>> {
// Handles object schema with nested ports
// Supports schema mutations
}
Port Plugins
Location: src/port/plugins/
Plugins provide validation and serialization for each port type:
interface PortPlugin<C extends IPortConfig, V> {
validateConfig(config: C): ValidationError[]
validateValue(value: V, config: C): ValidationError[]
serializeConfig(config: C): JSONValue
serializeValue(value: V): JSONValue
deserializeConfig(data: JSONValue): C
deserializeValue(data: JSONValue): V
getDefaultValue(config: C): V | undefined
}
Port Factory
File: src/port/factory/PortFactory.ts
class PortFactory {
static create<T extends IPortConfig>(config: T): PortInstance {
switch (config.type) {
case 'string': return new StringPort(config)
case 'number': return new NumberPort(config)
case 'boolean': return new BooleanPort(config)
case 'array': return new ArrayPort(config)
case 'object': return new ObjectPort(config)
case 'stream': return new StreamPort(config)
case 'enum': return new EnumPort(config)
case 'secret': return new SecretPort(config)
case 'any': return new AnyPort(config)
}
}
}
Transfer Rules
Location: src/port/transfer-rules/
Rules for port type compatibility during edge connections:
// Check if two ports can connect
const engine = getDefaultTransferEngine()
const canConnect = engine.canTransfer(sourcePort, targetPort)
// Rules include:
// - Same type โ direct transfer
// - Number โ String โ auto-convert
// - Array<T> โ Array<T> โ item-wise transfer
// - Object schema compatibility
Decorator System
Node Decorator
File: src/decorator/node.decorator.ts
@Node({
type: 'my-node', // Required: unique identifier
title: 'My Node', // Display name
category: 'math', // NodeCategory enum
description: 'Does X',
version: 1,
icon: 'calculator',
tags: ['arithmetic'],
flowPorts: { // System port configuration
flowIn: true,
flowOut: true,
error: true,
errorMessage: true,
},
})
class MyNode extends BaseNode { }
Port Direction Decorators
File: src/decorator/port-config.decorator.ts
@Input() // direction: 'input'
@Output() // direction: 'output'
@Passthrough() // direction: 'passthrough' (bidirectional)
Port Type Decorators
Files: scalar.decorator.ts, array.decorator.ts, object.decorator.ts, etc.
// Scalar types
@PortString({ defaultValue: '', minLength: 0, maxLength: 1000 })
@PortNumber({ defaultValue: 0, min: -Infinity, max: Infinity, step: 1 })
@PortBoolean({ defaultValue: false })
// Complex types
@PortArray({ itemConfig: { type: 'string' }, minLength: 0 })
@PortObject({ schema: mySchema })
@PortStream({ itemConfig: { type: 'string' } })
// Enum types
@PortEnum({ options: [{ value: 'a', label: 'Option A' }] })
// Special types
@PortSecret({ secretType: 'api-key' })
Port Metadata Decorators
@Name('customName') // Override port name
@Description('Port purpose') // Add description
@Title('Display Title') // Add title
@Id('custom-id') // Custom port ID
@DefaultValue(42) // Set default value
@Metadata('key', value) // Arbitrary metadata
Port Visibility Decorator
File: src/decorator/port-visibility.decorator.ts
@PortVisibility({
showIf: (instance: INode) => instance.getPort('mode')?.getValue() === 'advanced'
})
@Input()
@PortString()
advancedOption: string = ''
Complete Node Example
import {
Node, Input, Output,
PortString, PortNumber, PortBoolean, PortArray, PortObject,
Name, Description, PortVisibility
} from '@badaitech/chaingraph-types'
@Node({
type: 'text-processor',
title: 'Text Processor',
category: 'text',
description: 'Processes text with configurable options',
})
class TextProcessorNode extends BaseNode {
// String input with validation
@Input()
@PortString({ defaultValue: '', maxLength: 10000 })
@Description('Text to process')
text: string = ''
// Number input with range
@Input()
@PortNumber({ defaultValue: 100, min: 1, max: 1000 })
maxLength: number = 100
// Boolean flag
@Input()
@PortBoolean({ defaultValue: false })
uppercase: boolean = false
// Conditional visibility
@PortVisibility({ showIf: (node) => node.getPort('uppercase')?.getValue() === true })
@Input()
@PortString({ defaultValue: '' })
prefix: string = ''
// Array output
@Output()
@PortArray({ itemConfig: { type: 'string' } })
words: string[] = []
// Object output with schema
@Output()
@PortObject({
schema: {
properties: {
processed: { type: 'string' },
wordCount: { type: 'number' },
}
}
})
result: { processed: string, wordCount: number } = { processed: '', wordCount: 0 }
async execute(context: ExecutionContext): Promise<NodeExecutionResult> {
let processed = this.text.slice(0, this.maxLength)
if (this.uppercase) {
processed = (this.prefix + processed).toUpperCase()
}
this.words = processed.split(' ').filter(w => w.length > 0)
this.result = { processed, wordCount: this.words.length }
return {}
}
}
Flow & Execution Engine
Flow Class
File: src/flow/flow.ts
class Flow implements IFlow {
id: string
metadata: FlowMetadata
nodes: Map<string, INode>
edges: Map<string, IEdge>
// Internal components
eventQueue: EventQueue<FlowEvent>
propagationEngine: PropagationEngine
// Node operations
async addNode(node: INode): Promise<INode>
async addNodes(nodes: INode[]): Promise<INode[]>
async removeNode(nodeId: string): Promise<void>
// Edge operations
async addEdge(edge: IEdge): Promise<void>
async connectPorts(sourceNodeId, sourcePortId, targetNodeId, targetPortId): Promise<IEdge>
// Events
onEvent(handler: (event: FlowEvent) => void): () => void
// Validation
async validate(): Promise<FlowValidationResult>
}
ExecutionEngine
File: src/flow/execution-engine.ts
class ExecutionEngine {
// Execution queues
readyQueue: AsyncQueue<() => Promise<void>>
completedQueue: AsyncQueue<INode>
// Tracking
executingNodes: Set<string>
completedNodes: Set<string>
nodeDependencies: Map<string, number>
dependentsMap: Map<string, INode[]>
// Port-level resolution
resolvedPorts: Set<string>
sourcePortToWaitingNodes: Map<string, Set<string>>
// Event-driven nodes
eventListenerNodeIds: Set<string>
eventBoundNodes: Set<string>
// Concurrency control
semaphore: Semaphore
debugger: FlowDebugger | null
constructor(
flow: Flow,
context: ExecutionContext,
options?: ExecutionOptions,
onBreakpointHit?: (node: INode) => void
)
async execute(): Promise<void>
}
ExecutionOptions
interface ExecutionOptions {
execution?: {
maxConcurrency?: number // Default: 50
nodeTimeoutMs?: number // Default: 3600000 (1 hour)
flowTimeoutMs?: number // Default: 10800000 (3 hours)
}
debug?: boolean // Enable debugger
breakpoints?: string[] // Node IDs to break on
}
FlowDebugger
File: src/flow/debugger.ts
class FlowDebugger implements DebuggerController {
state: DebuggerState // 'running' | 'paused' | 'stepping' | 'stopped'
pause(): void
continue(): void
step(): void
stop(): void
addBreakpoint(nodeId: string): void
removeBreakpoint(nodeId: string): void
getState(): DebuggerState
}
PropagationEngine
File: src/flow/propagation/PropagationEngine.ts
Handles automatic data propagation when ports change:
class PropagationEngine {
actions: PropagationAction[]
async handleEvent(event: FlowEvent, flow: IFlow): Promise<ActionResult[]>
}
interface PropagationAction {
name: string
canExecute(context: ActionContext): boolean
execute(context: ActionContext): void | Promise<void>
}
interface ActionContext {
event: FlowEvent
flow: IFlow
sourcePort?: IPort
targetPort?: IPort
edge?: IEdge
sourceNode?: INode
targetNode?: INode
}
ExecutionContext
File: src/execution/execution-context.ts
class ExecutionContext {
// Identity
executionId: string
rootExecutionId?: string
parentExecutionId?: string
flowId?: string
userId?: string
// Timing
startTime: Date
executionDepth: number // Max 100
// Control
abortController: AbortController
// Integrations
integrations: IntegrationContext
// Event-driven execution
emittedEvents?: EmittedEvent[]
eventData?: EmittedEventContext
isChildExecution?: boolean
// Node resolution
getNodeById: (nodeId: string) => INode | undefined
findNodes: (predicate: (node: INode) => boolean) => INode[]
// Methods
emitEvent(event: EmittedEvent): void
getEmittedEvents(eventType?: string): EmittedEvent[]
resolvePort(nodeId: string, portId: string): void
isPortResolved(nodeId: string, portId: string): boolean
}
Key Files Reference
| File | Purpose | Lines |
|---|---|---|
src/port/base/IPort.ts | Port interface | 1-212 |
src/port/base/types.ts | Port config types | 1-150+ |
src/node/interfaces/inode-composite.ts | Composite interface | 1-86 |
src/node/base-node-compositional.ts | Node implementation | 1-100+ |
src/decorator/port-config.decorator.ts | Direction decorators | 1-118 |
src/decorator/port-visibility.decorator.ts | Visibility decorator | 1-138 |
src/decorator/metadata-storage.ts | Reflect metadata | 1-86 |
src/flow/execution-engine.ts | Execution engine | 1-100+ |
src/flow/debugger.ts | Flow debugger | 1-100+ |
src/flow/propagation/PropagationEngine.ts | Data propagation | 1-80+ |
src/execution/execution-context.ts | Runtime context | 1-100+ |
Quick Reference
| Need | Where | Export |
|---|---|---|
| Create a node | decorator/node.decorator.ts | @Node() |
| Input port | decorator/port-config.decorator.ts | @Input() |
| Output port | decorator/port-config.decorator.ts | @Output() |
| String port | decorator/scalar.decorator.ts | @PortString() |
| Number port | decorator/scalar.decorator.ts | @PortNumber() |
| Boolean port | decorator/scalar.decorator.ts | @PortBoolean() |
| Array port | decorator/array.decorator.ts | @PortArray() |
| Object port | decorator/object.decorator.ts | @PortObject() |
| Stream port | decorator/stream.decorator.ts | @PortStream() |
| Enum port | decorator/enum.decorator.ts | @PortEnum() |
| Conditional port | decorator/port-visibility.decorator.ts | @PortVisibility() |
| Create port instance | port/factory/PortFactory.ts | PortFactory.create() |
| Check compatibility | port/transfer-rules/engine.ts | TransferEngine |
Related Skills
chaingraph-concepts- Core domain conceptsport-system- Port types deep dive (planned)executor-architecture- How types are used in executionfrontend-architecture- How types render in UIdbos-patterns- Execution context in DBOS
Repository
