lumora-ir
v1.1.2
Published
Lumora Intermediate Representation system for framework-agnostic UI components
Downloads
636
Maintainers
Readme
@lumora/ir
Lumora Intermediate Representation (IR) system - A framework-agnostic representation for UI components that enables seamless conversion between React and Flutter.
Overview
The Lumora IR system provides:
- Framework-agnostic representation: Capture UI structure, props, state, and behavior independent of any specific framework
- JSON Schema validation: Ensure IR integrity with comprehensive validation
- Versioning and storage: Store IR with full version history and change tracking
- Migration system: Automatically migrate IR between schema versions
- Utility functions: Rich set of tools for working with IR structures
Installation
npm install @lumora/irCLI Usage
Lumora IR includes a powerful CLI for converting between React and Flutter:
# Convert React to Flutter
lumora convert src/Button.tsx
# Convert Flutter to React
lumora convert lib/button.dart
# Watch mode for live conversion
lumora convert src/App.tsx --watch
# Dry run to preview changes
lumora convert src/Button.tsx --dry-runSee CLI Documentation for complete usage guide.
Quick Start
Creating IR
import { createIR, createNode } from '@lumora/ir';
// Create a simple IR structure
const ir = createIR(
{
sourceFramework: 'react',
sourceFile: 'App.tsx',
generatedAt: Date.now(),
},
[
createNode('Container', { width: 100, height: 200 }, [
createNode('Text', { content: 'Hello World' }),
createNode('Button', { onPress: 'handlePress' }),
]),
]
);Validating IR
import { getValidator } from '@lumora/ir';
const validator = getValidator();
// Validate IR
const result = validator.validate(ir);
if (!result.valid) {
console.error('Validation errors:', result.errors);
}
// Or validate and throw on error
validator.validateOrThrow(ir);Storing IR
import { IRStorage } from '@lumora/ir';
const storage = new IRStorage('.lumora/ir');
// Store IR with versioning
const entry = storage.store('my-component', ir);
console.log(`Stored version ${entry.version}`);
// Retrieve latest version
const retrieved = storage.retrieve('my-component');
// Retrieve specific version
const v1 = storage.retrieve('my-component', 1);
// Get version history
const history = storage.getHistory('my-component');
// Check if IR has changed
if (storage.hasChanged('my-component', updatedIR)) {
storage.store('my-component', updatedIR);
}Migrating IR
import { getMigrator } from '@lumora/ir';
const migrator = getMigrator();
// Check if migration is needed
if (migrator.needsMigration(oldIR, '1.0.0')) {
// Migrate to latest version
const migratedIR = migrator.migrate(oldIR, '1.0.0');
}
// Register custom migration
migrator.registerMigration({
fromVersion: '1.0.0',
toVersion: '1.1.0',
migrate: (ir) => {
// Transform IR structure
return transformedIR;
},
});Working with Nodes
import {
findNodeById,
findNodesByType,
countNodes,
getMaxDepth,
traverseNodes,
} from '@lumora/ir';
// Find node by ID
const node = findNodeById(ir.nodes, 'node_123');
// Find all nodes of a type
const textNodes = findNodesByType(ir.nodes, 'Text');
// Count total nodes
const total = countNodes(ir.nodes);
// Get tree depth
const depth = getMaxDepth(ir.nodes);
// Traverse tree with visitor
traverseNodes(ir.nodes, (node, depth) => {
console.log(`${' '.repeat(depth * 2)}${node.type}`);
});IR Structure
LumoraIR
interface LumoraIR {
version: string; // Semantic version (e.g., "1.0.0")
metadata: IRMetadata;
nodes: LumoraNode[];
theme?: ThemeDefinition;
navigation?: NavigationDefinition;
}LumoraNode
interface LumoraNode {
id: string; // Unique identifier
type: string; // Widget/component type
props: Record<string, any>; // Properties
children: LumoraNode[]; // Child nodes
state?: StateDefinition; // State management
events?: EventDefinition[]; // Event handlers
metadata: NodeMetadata; // Source metadata
}StateDefinition
interface StateDefinition {
type: 'local' | 'global' | 'async';
variables: StateVariable[];
}
interface StateVariable {
name: string;
type: string;
initialValue: any;
mutable: boolean;
}EventDefinition
interface EventDefinition {
name: string; // Event name (e.g., "onPress")
handler: string; // Handler function code
parameters: Parameter[];
}API Reference
Validator
validate(ir: any): ValidationResult- Validate IR against schemavalidateOrThrow(ir: any): void- Validate and throw on errorisValidVersion(version: string): boolean- Check version formatvalidateNode(node: any): ValidationResult- Validate single node
Storage
store(id: string, ir: LumoraIR): IRStorageEntry- Store IR with versioningretrieve(id: string, version?: number): IRStorageEntry | null- Retrieve IRgetCurrentVersion(id: string): number- Get current version numbergetHistory(id: string): IRStorageEntry[]- Get version historydelete(id: string): boolean- Delete IR and historylist(): string[]- List all stored IRshasChanged(id: string, ir: LumoraIR): boolean- Check if IR changed
Migrator
migrate(ir: any, targetVersion: string): LumoraIR- Migrate IR to versionneedsMigration(ir: any, targetVersion: string): boolean- Check if migration neededgetCurrentVersion(): string- Get current IR versionregisterMigration(migration: IRMigration): void- Register custom migration
Utilities
createIR(metadata: IRMetadata, nodes?: LumoraNode[]): LumoraIR- Create IRcreateNode(type: string, props?, children?, lineNumber?): LumoraNode- Create nodegenerateNodeId(): string- Generate unique node IDcloneIR(ir: LumoraIR): LumoraIR- Deep clone IRcloneNode(node: LumoraNode): LumoraNode- Deep clone nodefindNodeById(nodes: LumoraNode[], id: string): LumoraNode | null- Find nodefindNodesByType(nodes: LumoraNode[], type: string): LumoraNode[]- Find nodes by typecountNodes(nodes: LumoraNode[]): number- Count total nodesgetMaxDepth(nodes: LumoraNode[]): number- Get tree depthtraverseNodes(nodes: LumoraNode[], visitor: Function): void- Traverse tree
Testing
npm testLicense
MIT
