Architecture Overview
This document provides a high-level overview of the ReX architecture, explaining the system’s structure, components, and design principles.
Architectural Principles
The ReX architecture is built on the following core principles:
- Composition Over Inheritance: Function composition as the primary mechanism for extending functionality
- Clear Layer Boundaries: Well-defined responsibilities and interfaces between layers
- Environmental Adaptability: Consistent API with environment-specific implementations
- Progressive Enhancement: Core functionality with optional advanced capabilities
- Pure Functions: Minimizing side effects and enhancing testability
System Layers
The system is organized into five distinct layers:
┌─────────────────────────────────┐
│ Integration Layer │ React hooks, components, API surface
├─────────────────────────────────┤
│ Content Facade Layer │ ContentStore, Registry interfaces
├─────────────────────────────────┤
│ Enhancement Layer │ Middleware, composition functions
├─────────────────────────────────┤
│ Storage Adapter Layer │ Environment-specific storage adapters
├─────────────────────────────────┤
│ Foundation Layer │ Types, errors, utilities, telemetry
└─────────────────────────────────┘
Layer Details
1. Integration Layer
This layer connects ReX to application frameworks and environments:
- React Integration: Hooks and components for React applications
- Node.js Integration: Express middleware and server-side utilities
- API Surface: Public JavaScript/TypeScript API
2. Content Facade Layer
This layer provides high-level interfaces for content operations:
- ContentStore: Primary interface for content operations
- ContentRegistry: Registry for managing multiple content stores
- Operation Factories: Functions creating configured operations
3. Enhancement Layer
This layer enhances content operations through middleware:
- Middleware Chain: Sequential execution of middleware functions
- Context Propagation: Shared context for middleware execution
- Composition Functions: Utilities for combining middleware and enhanced stores
4. Storage Adapter Layer
This layer abstracts storage backend details:
- Environment-specific Adapters: Filesystem, IndexedDB, HTTP, etc.
- Adapter Capability Detection: Runtime identification of available features
- Serialization/Deserialization: Converting between content and storage formats
5. Foundation Layer
This layer provides core building blocks:
- Type Definitions: Core types like Content, ContentMetadata, etc.
- Error System: Specialized error classes with context
- Utilities: Helper functions for common operations
- Telemetry: Logging, tracing, and monitoring
Component Architecture
Core Components
The primary components of the system include:
ContentStore
The ContentStore is the primary interface for content operations:
interface ContentStore {
// Core operations
read(uri: string, options?: ContentReadOptions): Promise<Content>
write(
uri: string,
content: Content,
options?: ContentWriteOptions
): Promise<void>
delete(uri: string, options?: ContentDeleteOptions): Promise<void>
list(pattern: string, options?: ContentListOptions): Promise<string[]>
exists(uri: string, options?: ContentExistsOptions): Promise<boolean>
// Observation
observe(
observer: ContentChangeObserver,
options?: ObserveOptions
): Unsubscribe
// Resource management
dispose(): Promise<void>
}
ContentAdapter
The ContentAdapter connects to specific storage backends:
interface ContentAdapter {
// Core operations
read(uri: string, options?: any): Promise<Content>
write(uri: string, content: Content, options?: any): Promise<void>
delete(uri: string, options?: any): Promise<void>
list(pattern: string, options?: any): Promise<string[]>
// Optional operations
exists?(uri: string, options?: any): Promise<boolean>
// Events (if supported)
events?: EventEmitter
// Resource management
dispose(): Promise<void>
}
Middleware
Middleware functions enhance operations:
type Middleware<T = ContentContext> = (
context: T,
next: () => Promise<T>
) => Promise<T>
interface ContentContext {
operation: string
uri: string
content?: Content
options?: Record<string, any>
result?: any
}
Data Flow
The standard data flow for a content operation:
┌──────────┐ ┌──────────┐ ┌──────────────┐ ┌──────────┐ ┌──────────┐
│ Client │───▶│ Store │───▶│ Middleware │───▶│ Adapter │───▶│ Storage │
│ │◀───│ │◀───│ Chain │◀───│ │◀───│ │
└──────────┘ └──────────┘ └──────────────┘ └──────────┘ └──────────┘
- Client calls store operation (e.g.,
store.read('blog/post.md')
) - Store prepares operation context and initiates middleware chain
- Middleware processes the context (validation, caching, etc.)
- Adapter translates to storage-specific operations
- Storage performs the physical operation
- Result flows back through adapter, middleware chain, and store
- Client receives the final result
Extension Mechanisms
Middleware
Middleware is the primary extension mechanism, enhancing content operations with additional capabilities:
// Create a simple logging middleware
function withLogging(options = {}): Middleware {
return async (context, next) => {
console.log(`Before ${context.operation}: ${context.uri}`)
// Continue the middleware chain
const result = await next()
console.log(`After ${context.operation}: ${context.uri}`)
return result
}
}
// Apply middleware to a store
const enhancedStore = pipe(baseStore, withLogging(), withValidation(schema))
Custom Adapters
Custom adapters allow integration with different storage systems:
// Create custom adapter
const customAdapter = createAdapter({
read: async uri => {
// Custom read implementation
const data = await customReadImplementation(uri)
return {
data,
contentType: determineContentType(uri),
metadata: {},
}
},
write: async (uri, content) => {
// Custom write implementation
await customWriteImplementation(uri, content)
},
delete: async uri => {
// Custom delete implementation
await customDeleteImplementation(uri)
},
list: async pattern => {
// Custom list implementation
return customListImplementation(pattern)
},
})
Environment Adapability
The system adapts to different runtime environments:
Node.js (Server)
In Node.js, the system leverages filesystem capabilities:
// Create content store with filesystem adapter
const store = createContentStore({
adapter: createFileSystemAdapter({
baseDir: './content',
watch: true, // Enable real-time file watching
}),
})
Browser
In browsers, the system uses IndexedDB, localStorage, or HTTP:
// Create content store with IndexedDB adapter
const store = createContentStore({
adapter: createIndexedDBAdapter({
dbName: 'content-store',
storeName: 'content',
}),
})
Service Worker
For offline capabilities, the system uses service worker caching:
// Create content store with service worker adapter
const store = createContentStore({
adapter: createServiceWorkerAdapter({
cacheStrategy: 'network-first',
}),
})
Architectural Decisions
The key architectural decisions are documented in Architecture Decision Records (ADRs):
Related Resources
For more detailed information:
- Layer Boundaries: Detailed layer responsibilities
- Component Diagram: Visual component relationships
- Data Flow Diagram: Operation flow visualization
- Implementation Standards: Coding guidelines