hataori
v1.1.1
Published
HATAORI - TypeScript Merkle Lambda Linker SWC Plugin
Downloads
20
Maintainers
Readme
HATAORI - TypeScript Merkle Lambda Linker SWC Plugin
HATAORI is a SWC plugin that implements a content-addressed function management system similar to Unison in the TypeScript/JavaScript ecosystem.
Features
- 🚀 Content Addressing: Manage functions by hash IDs (Unison-style approach)
- 🛡️ Capability-Based Side Effect Control: Pure functional programming with explicit capabilities
- 🔗 Merkle Linking: Deterministic hash generation including dependencies
- ⚡ SWC Integration: High-performance TypeScript transformation
- 🌐 Distributed Execution: Hash-based function distribution and execution
Installation
npm install hataoriQuick Start
1. SWC Configuration
Create a .swcrc file:
{
"jsc": {
"experimental": {
"plugins": [
["hataori", {
"enableCapabilities": true,
"hashAlgorithm": "blake3",
"storeBackend": "memory"
}]
]
}
}
}2. Example Code
// Pure function - automatically content-addressed
export const add = (a: number, b: number): number => a + b;
// Function using capabilities
type Capabilities = { clock: { now(): number } };
export const getTimestamp = (A: Capabilities) => () =>
A.clock.now();3. Execution
import { RuntimeExecutor } from 'hata';
// Execute function by hash address
const executor = new RuntimeExecutor(context);
const result = await executor.execute('u#abc123...', [1, 2]);Architecture
HATAORI consists of the following process network:
Source Code → AST Parse → Function Extract → Normalize → Dependency Analysis
↓ ↓ ↓ ↓ ↓
Hash Gen → CAS Store → Name Resolve → Linker → Runtime ExecuteContent Addressed Store (CAS)
CAS is a hash-based storage system that operates within the SWC plugin:
- Session-based: Independent CAS instance per compilation session
- In-memory: Default memory storage (discarded after compilation)
- Persistence options: File/IPFS-based persistent storage available
- Function management: Store/retrieve function definitions by hash and resolve dependencies
// CAS operation within plugin
const cas = new MemoryCAS(); // Created per file compilation
// Store function by hash
await cas.store(functionHash, functionDefinition);
// Retrieve dependency from CAS
const dependency = await cas.retrieve(dependencyHash);CAS Operation Flow
CAS operation within SWC plugin:
// 1. Create new CAS for each file compilation
Program(program) {
const cas = new MemoryCAS(); // Per-session
// 2. Store functions in CAS during processing
const functions = extractFunctions(program);
for (const func of functions) {
const hash = generateHash(func);
await cas.store(hash, func); // Store by hash
}
// 3. Retrieve dependencies from CAS
const dependencies = await resolveDependencies(func.dependencies, cas);
// 4. CAS discarded after compilation (in-memory)
}Process Nodes
- source_parser: Parse TypeScript to AST using SWC
- function_extractor: Extract top-level functions/constants
- ast_normalizer: Normalize AST (remove comments/whitespace)
- dependency_analyzer: Analyze function dependencies
- hash_generator: Generate Merkle hashes
- cas_store: Store in CAS (operates within plugin)
- name_resolver: Resolve names to hashes
- linker: Generate manifest and link
- capability_checker: Validate side effect control
- runtime_executor: Function execution runtime
Capabilities System
HATAORI controls side effects through explicit "capabilities":
// Predefined capabilities
interface Clock { now(): number; sleep(ms: number): Promise<void> }
interface Random { generate(): number; seed(s: number): void }
interface Http { get(url: string): Promise<string> }
interface Console { log(...args: any[]): void }
// Usage example
export const logTime = (A: { clock: Clock; console: Console }) => () => {
const time = A.clock.now();
A.console.log(`Current time: ${time}`);
};CAS Operation within SWC Plugin
Per-Compilation Session CAS
CAS operates within the SWC plugin runtime and provides independent storage for each compilation session:
// .swcrc
{
"jsc": {
"experimental": {
"plugins": [
["hataori", {
"storeBackend": "memory" // Create new CAS per file
}]
]
}
}
}
// For each .ts file compilation:
// 1. Create new CAS instance
// 2. Store functions in CAS
// 3. Resolve dependencies from CAS
// 4. Discard CAS after compilationCross-File CAS Sharing
Using persistence options allows CAS sharing across compilation sessions:
const plugin = hata({
storeBackend: 'file' // or 'ipfs'
});
// In this case, CAS is shared across multiple .ts files,
// enabling function definition reuse and dependency resolutionDevelopment Experience
Safe Renaming
// Original function
export const oldName = (x: number) => x * 2;
// After renaming, hash remains unchanged, references auto-resolved
export const newName = (x: number) => x * 2;Deterministic Testing
// Test with mock abilities
const testExecutor = executor.createTestContext();
const result = await testExecutor.execute(address, args);API Reference
Main Function
import { hata } from 'hataori';
// Use as SWC plugin
const plugin = hata({
enableCapabilities: true,
hashAlgorithm: 'blake3',
storeBackend: 'memory' // 'memory' | 'file' | 'ipfs'
});
// CAS Backend Options:
// - 'memory': Temporary storage per compilation session (default)
// - 'file': File system-based persistent storage
// - 'ipfs': Distributed storage (IPFS)CAS Jsonnet Export
CAS content can be exported as programmable Jsonnet format:
// Export CAS content as Jsonnet
const jsonnetOutput = await cas.exportToJsonnet({
includeMetadata: true,
includeComments: true,
compactAST: true,
version: '1.0.0',
});
// Save as Jsonnet file
fs.writeFileSync('cas-export.jsonnet', jsonnetOutput);Jsonnet Utility Functions
Generated Jsonnet files include the following utility functions:
// Search by function name
local cas = import "cas-export.jsonnet";
local addFunc = cas.getFunctionByName("add");
// Get all function names
local allNames = cas.getAllFunctionNames(); // ["add", "multiply", ...]
// Get exported functions only
local exports = cas.getExportedFunctions();
// Get dependency graph
local deps = cas.getDependencyGraph(); // { "add": [], "compute": ["add", "multiply"] }Export Options
await cas.exportToJsonnet({
includeMetadata: true, // Include version and timestamp
includeComments: true, // Include comments
compactAST: true, // Compact AST for size reduction
version: '1.0.0', // Version information
filterFunctions: (func) => func.isExported // Specific functions only
});Usage Examples
# Export CAS content as Jsonnet
npm run generate-examples
# Manipulate generated Jsonnet files
jsonnet -e 'local cas = import "examples/cas-compact-export.jsonnet"; cas.getFunctionByName("add")'
# Display dependency graph
jsonnet -e 'local cas = import "examples/cas-compact-export.jsonnet"; cas.getDependencyGraph()'Runtime Execution
import { RuntimeExecutor } from 'hata';
const executor = new RuntimeExecutor(context);
// Execute function
const result = await executor.execute('u#hash...', args);
// Create test context
const testExecutor = executor.createTestContext();Roadmap
- [x] Core architecture and process network
- [x] SWC plugin implementation
- [x] AST processing and function extraction
- [x] Merkle hash generation
- [x] Linking and manifest generation
- [x] Capabilities system
- [x] Runtime execution engine
- [ ] IPFS backend integration
- [ ] VS Code extension
- [ ] Distributed execution runtime
- [ ] Performance optimizations
Contributing
- Fork the Project
- Create your Feature Branch (
git checkout -b feature/AmazingFeature) - Commit your Changes (
git commit -m 'Add some AmazingFeature') - Push to the Branch (
git push origin feature/AmazingFeature) - Open a Pull Request
License
Distributed under the Apache License, Version 2.0. See LICENSE for more information.
Related Projects
- Unison Language - Inspiration source
- SWC - Transformation framework
- IPLD - Distributed data structures
CAS Design Principles
Importance of SWC Plugin Operation
CAS functions as part of the compilation process with the following characteristics:
- Session Isolation: Independent CAS instance per compilation session
- Memory Efficiency: In-memory operation by default (auto-discarded after compilation)
- Extensibility: File/IPFS-based persistent storage options
- Function-Centric: Hash-based function management and dependency resolution
// CAS Lifecycle
Program(program) {
// 1. Create CAS when plugin execution starts
const cas = new CAS();
// 2. Use CAS during compilation
processFunctions(program, cas);
// 3. Discard CAS when plugin execution ends
// (auto-discarded for in-memory, saved for persistent)
}HATAORI - Functions by hash, purity by capabilities, distribution by network.
