ignorant
v2.0.2
Published
Pre-compile OOP inheritance into standalone, dependency-free classes. Flatten class hierarchies at build time for simplified distribution.
Downloads
20
Maintainers
Readme
🚀 ignorant
A robust AST-based JavaScript class inheritance compiler that accurately flattens class hierarchies through proper AST parsing and manipulation.
Pure AST Manipulation
- No more regex string operations
- Uses Acorn for parsing and Astring for code generation
- Proper AST traversal and transformation
Accurate Inheritance Handling
- Correctly processes constructor chains
- Proper method override resolution
- Maintains member order and visibility
Comprehensive Member Support
- Static and instance fields
- Public and private members
- Getters and setters
- Computed property names
- Method overrides with proper resolution
Robust Error Handling
- Circular inheritance detection
- Missing parent class validation
- Detailed error reporting
- Graceful degradation
Better Code Organization
- Object-oriented design with ClassCompiler class
- Modular methods for easy extension
- Clear separation of concerns
- Comprehensive documentation
📦 Installation
npm install ignorant🎓 Usage
Basic Usage
import { compileClasses } from 'ignorant';
const code = `
class Animal {
constructor(name) {
this.name = name;
}
makeSound() {
console.log('Some sound');
}
}
export class Dog extends Animal {
constructor(name, breed) {
super(name);
this.breed = breed;
}
makeSound() {
console.log('Woof!');
}
fetch() {
console.log('Fetching ball');
}
}
`;
const result = await compileClasses(code);
console.log(result.code);Output:
export class Dog {
// Constructor inlines entire chain
constructor(name, breed) {
// inherited from Animal constructor
this.name = name;
this.breed = breed;
}
// inherited from Animal
makeSound() {
console.log('Woof!'); // Overridden version
}
fetch() {
console.log('Fetching ball');
}
}Advanced Usage with Options
import { ClassCompiler } from 'ignorant';
const compiler = new ClassCompiler({
excludeIntermediate: true, // Skip classes that are extended by others
exportOnly: false, // Include non-exported classes
preserveComments: true, // Add source annotations
validateInheritance: true // Validate inheritance chains
});
const result = await compiler.compile(code);
// Access detailed information
console.log('Class Map:', result.classMap);
console.log('Inheritance Graph:', result.inheritanceGraph);
console.log('Errors:', result.errors);
console.log('Compiled Code:', result.code);Extract Individual Classes
import { extractClasses } from 'ignorant';
const code = `
class A {}
class B extends A {}
export class C extends B {}
`;
const classes = extractClasses(code);
// Returns: [
// { name: 'A', code: 'class A {}', node: {...} },
// { name: 'B', code: 'class B extends A {}', node: {...} },
// { name: 'C', code: 'export class C extends B {}', node: {...} }
// ]⚙️ Configuration Options
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| excludeIntermediate | boolean | true | Exclude intermediate classes that are extended by other classes |
| exportOnly | boolean | false | Only compile exported classes |
| preserveComments | boolean | true | Add comments indicating source class for inherited members |
| validateInheritance | boolean | true | Validate inheritance chains for errors |
🔍 How It Works
1. Parsing Phase
const ast = acorn.parse(code, {
ecmaVersion: 'latest',
sourceType: 'module',
locations: true,
ranges: true
});2. Class Registry Building
- Identifies all class declarations
- Tracks export information
- Builds inheritance graph
- Categorizes members by type
3. Validation Phase
- Detects circular inheritance
- Checks for missing parent classes
- Validates member compatibility
4. Transformation Phase
- Collects members from entire inheritance chain
- Resolves method overrides
- Inlines constructor chains
- Flattens class hierarchy
5. Code Generation
- Uses Astring to generate code from AST
- Formats with Prettier
- Preserves export declarations
📊 Member Categories
The compiler categorizes and orders members as follows:
- Static Private Fields
- Static Public Fields
- Static Private Methods
- Static Public Methods
- Instance Private Fields
- Instance Public Fields
- Constructor (inlined from entire chain)
- Getters and Setters
- Instance Private Methods
- Instance Public Methods
🎯 Key Features
Constructor Chain Inlining
The compiler properly inlines constructor chains by:
- Collecting all constructors in inheritance order
- Removing
super()calls - Preserving all initialization logic
- Maintaining proper execution order
Before:
class A {
constructor(x) {
this.x = x;
}
}
class B extends A {
constructor(x, y) {
super(x);
this.y = y;
}
}After:
class B {
constructor(x, y) {
// from A constructor
this.x = x;
this.y = y;
}
}Method Override Resolution
The compiler correctly identifies and resolves method overrides:
class Animal {
makeSound() { return 'generic'; }
}
class Dog extends Animal {
makeSound() { return 'woof'; } // Overrides Animal.makeSound
}Private Member Handling
Respects private fields and methods:
class Base {
#privateField = 0;
#privateMethod() {
return this.#privateField;
}
}
class Derived extends Base {
// Private members from Base are preserved
}🧪 Testing
Run the comprehensive test suite:
node test-class-compiler.jsThis will run tests for:
- Simple inheritance chains
- Multiple inheritance branches
- Getters and setters
- Private members
- Export modes
- Class extraction
- Performance benchmarks
🔧 API Reference
ClassCompiler
The main compiler class.
Constructor
new ClassCompiler(options)Methods
compile(code)
Compiles the given code and returns a result object.
Returns:
{
code: string, // Compiled code
errors: Array, // Compilation errors/warnings
classMap: Map, // Class information map
inheritanceGraph: Map // Inheritance relationships
}static extractClasses(code)
Extracts individual class definitions from code.
Returns:
[{
name: string, // Class name
code: string, // Class source code
node: object // AST node
}]Convenience Functions
compileClasses(code, options)
Quick compilation without creating a ClassCompiler instance.
extractClasses(code)
Quick class extraction without creating a ClassCompiler instance.
🚨 Error Types
The compiler reports the following error types:
MISSING_PARENT: Parent class not foundCIRCULAR_INHERITANCE: Circular inheritance detectedCOMPILATION_ERROR: General compilation error
Example error object:
{
type: 'MISSING_PARENT',
class: 'Dog',
parent: 'Animal',
message: 'Class "Dog" extends "Animal" which is not defined'
}🎨 Code Quality
Pure AST manipulation - No string regex operations
Type-safe operations - Proper AST node handling
Comprehensive error handling - Graceful failure modes
Well-documented - Clear code comments and documentation
Modular design - Easy to extend and maintain
Migration Steps
// v1.0
import { mergeClasses, transform } from './old-version.js';
const result = await transform(code);
// v2.0
import { compileClasses } from 'ignorant';
const result = await compileClasses(code);
console.log(result.code); // Access the compiled code🤝 Contributing
Contributions are welcome! This is a clean, well-structured codebase designed for easy extension.
📝 License
MIT
🙏 Acknowledgments
Built with:
Made with 🙃 for better JavaScript inheritance handling
