Registry Architecture
Note: This document focuses specifically on the Registry module architecture. For a high-level overview of the entire architecture, see the Architecture Overview.
The Ham Radio Registry is built with a modular, extensible architecture that supports both official and third-party radio modules. This page explains the technical design and how the registry components work together.
System Overview
The registry consists of several key components that work together to provide a unified interface for discovering and managing radio configurations:
Core Components
1. RadioConfigRegistry Interface
The main interface that applications interact with:
interface RadioConfigRegistry {
// Discovery
discoverConfigurations(): Promise<RegistryRadio[]>;
getConfiguration(configId: string): Promise<RegistryRadio | null>;
getConfigurationsByManufacturer(manufacturer: string): Promise<RegistryRadio[]>;
getConfigurationsByModule(moduleId: string): Promise<RegistryRadio[]>;
// Management
validateConfiguration(config: RegistryRadio): ValidationResult;
registerConfiguration(config: RegistryRadio): Promise<void>;
installPlugin(moduleId: string): Promise<void>;
listInstalledPlugins(): Promise<PluginModule[]>;
// Codec Support
getCodec(modelId: RadioModelId): Promise<RadioCodec | null>;
}2. NpmBasedConfigRegistry Implementation
The main implementation that handles npm-based discovery:
class NpmBasedConfigRegistry implements RadioConfigRegistry {
private configCache = new Map<string, RegistryRadio>();
private pluginCache = new Map<string, PluginModule>();
private codecCache = new Map<string, RadioCodec>();
private sharedComponentManager: SharedComponentManager;
private npmClient: NpmClient;
private logger: ILogLayer;
// Implementation methods...
}3. Shared Component Management
Handles loading and managing shared components across radio models:
interface SharedComponentManager {
loadSchema(schemaPath: string): Promise<any>;
loadProtocol(protocolPath: string): Promise<any>;
loadCodec(codecPath: string, config: any): Promise<RadioCodec>;
resolveReference(reference: string, basePath: string): string;
}4. NPM Client
Interfaces with the npm registry for package discovery and validation:
interface NpmClient {
getPackageInfo(packageName: string): Promise<any>;
searchPackages(query: string): Promise<NpmPluginInfo[]>;
getPackageStats(packageName: string): Promise<any>;
validatePackage(packageName: string): Promise<boolean>;
}Data Flow
1. Configuration Discovery
2. Plugin Installation
3. Codec Loading
Module Structure
Standard Module Layout
radio-module-manufacturer/
├── package.json
├── configs/
│ ├── model1.json
│ └── model2.json
├── src/shared/
│ ├── schemas/
│ │ ├── channel-schema.json
│ │ └── settings-schema.json
│ └── memory-maps/
│ └── model-settings.json
└── README.mdPackage.json Configuration
{
"name": "@springfield/radio-module-baofeng",
"version": "1.0.0",
"description": "Radio module for Baofeng UV-5R series",
"keywords": ["ham-radio", "radio-module", "baofeng"],
"springfield": {
"pluginType": "radio-module",
"version": "1.0.0",
"manufacturer": "Baofeng",
"supportedRadios": ["baofeng-uv5r"],
"capabilities": {
"dslProtocols": true,
"memoryRead": true,
"memoryWrite": true
},
"configPath": "configs",
"sharedPath": "src/shared"
},
"peerDependencies": {
"@springfield/ham-radio-api": "^12.0.0"
}
}Configuration Schema
Radio Configuration Structure
interface RegistryRadio {
$schema?: string;
id: {
model: string;
name: string;
manufacturer: string;
};
version: string;
description: string;
capabilities: RadioCapabilities;
serialConfig: SerialConfig;
memoryConfig: MemoryConfig;
readMemory: ProtocolStep[];
writeMemory: ProtocolStep[];
settingsSchema: {
model: string;
settingsSchema: any;
channelSchema: any;
};
codec?: CodecConfig;
metadata: RadioConfigMetadata;
}Shared Component References
Configurations can reference shared components:
{
"settingsSchema": {
"model": "baofeng-uv5r",
"settingsSchema": {
"$ref": "src/shared/schemas/settings-schema.json"
},
"channelSchema": {
"$ref": "src/shared/schemas/channel-schema.json"
}
},
"memoryMap": {
"$ref": "src/shared/memory-maps/uv5r-settings.json"
},
"codec": {
"type": "memoryMap"
}
}Security Architecture
1. Module Validation
- Package.json validation
- Required field checking
- Version compatibility verification
- Security issue detection
2. Configuration Validation
- Schema validation
- File path verification
- Reference resolution checking
- Malicious content detection
3. Code Execution Safety
- Sandboxed codec loading
- Dynamic import validation
- Code pattern analysis
- Execution environment isolation
4. Tamper Detection
- Checksum verification
- Signature validation
- File integrity checking
- Modification detection
Caching Strategy
The registry implements a multi-level caching strategy:
1. Configuration Cache
- Caches loaded configurations by model ID
- Reduces file system access
- Improves response times
2. Plugin Cache
- Caches discovered plugin modules
- Avoids repeated node_modules scanning
- Maintains plugin metadata
3. Codec Cache
- Caches instantiated codecs by model ID
- Reduces codec factory overhead
- Improves performance for repeated access
4. NPM Cache
- Caches npm registry responses
- Reduces network requests
- Improves search performance
Error Handling
The registry implements comprehensive error handling:
1. Graceful Degradation
- Continues operation if individual modules fail
- Provides fallback mechanisms
- Logs errors for debugging
2. Validation Errors
- Detailed error messages
- Specific validation failures
- Suggested fixes
3. Network Errors
- Retry mechanisms
- Timeout handling
- Offline mode support
4. Security Errors
- Immediate failure on security issues
- Detailed security reporting
- Audit trail maintenance
Performance Considerations
1. Lazy Loading
- Configurations loaded on demand
- Codecs instantiated when needed
- Shared components cached after first load
2. Parallel Processing
- Concurrent module discovery
- Parallel configuration loading
- Async validation processes
3. Memory Management
- Efficient caching strategies
- Memory leak prevention
- Resource cleanup
4. File System Optimization
- Minimized file system access
- Efficient directory scanning
- Smart file watching
Extensibility Points
The architecture provides several extension points:
1. Custom Registry Implementations
- Implement
RadioConfigRegistryinterface - Support different storage backends
- Custom discovery mechanisms
2. Custom Shared Component Managers
- Implement
SharedComponentManagerinterface - Support different component types
- Custom loading strategies
3. Custom NPM Clients
- Implement
NpmClientinterface - Support different registries
- Custom search algorithms
4. Plugin Hooks
- Pre-installation hooks
- Post-discovery hooks
- Validation hooks
This architecture provides a solid foundation for a scalable, secure, and extensible radio configuration management system.