A powerful, type-safe preference injection system for dynamic configuration management in Node.js and TypeScript applications.
-
Multiple Providers: File-based, environment variables, API, and in-memory storage
-
Priority System: Resolve conflicts between providers using customizable strategies
-
Type Safety: Full TypeScript support with generic type helpers
-
Caching: LRU and TTL caching strategies for performance
-
Validation: Schema-based and custom validation rules
-
Encryption: AES-256-GCM encryption for sensitive preferences
-
Audit Logging: Track all preference operations
-
Migrations: Version and migrate preference schemas
-
React Integration: Hooks and context providers
-
Express Middleware: RESTful API and request helpers
-
CLI Tool: Command-line interface for preference management
import { PreferenceInjector, MemoryProvider } from '@hyperpolymath/preference-injector';
// Create an injector with an in-memory provider
const injector = new PreferenceInjector({
providers: [new MemoryProvider()],
});
await injector.initialize();
// Set preferences
await injector.set('theme', 'dark');
await injector.set('fontSize', 14);
// Get preferences
const theme = await injector.get('theme');
console.log('Theme:', theme); // 'dark'
// Get with type safety
const fontSize = await injector.getTyped<number>('fontSize');
console.log('Font Size:', fontSize); // 14In-memory storage for runtime preferences:
import { MemoryProvider, PreferencePriority } from '@hyperpolymath/preference-injector';
const provider = new MemoryProvider(PreferencePriority.NORMAL);JSON or .env file-based storage:
import { FileProvider } from '@hyperpolymath/preference-injector';
const provider = new FileProvider({
filePath: './config.json',
priority: PreferencePriority.NORMAL,
watchForChanges: true,
format: 'json', // or 'env'
});Environment variable integration:
import { EnvProvider } from '@hyperpolymath/preference-injector';
const provider = new EnvProvider({
prefix: 'APP_',
priority: PreferencePriority.HIGHEST,
parseValues: true,
});Use multiple providers with automatic conflict resolution:
const injector = new PreferenceInjector({
providers: [
new EnvProvider({ priority: PreferencePriority.HIGHEST }),
new FileProvider({ filePath: './config.json', priority: PreferencePriority.NORMAL }),
new MemoryProvider(PreferencePriority.LOW),
],
conflictResolution: ConflictResolution.HIGHEST_PRIORITY,
});Add validation rules to ensure preference values are valid:
import { CommonValidationRules } from '@hyperpolymath/preference-injector';
const validator = injector.getValidator();
// Add built-in validation rules
validator.addRule('email', CommonValidationRules.email());
validator.addRule('age', CommonValidationRules.numberRange(0, 150));
validator.addRule('username', CommonValidationRules.stringLength(3, 20));
// Set with validation
await injector.set('email', 'user@example.com', { validate: true });Define schemas for your preferences:
import { SchemaBuilder } from '@hyperpolymath/preference-injector';
const schema = new SchemaBuilder()
.string('apiUrl', { required: true, pattern: /^https?:\/\// })
.number('timeout', { min: 0, max: 30000, default: 5000 })
.boolean('debug', { default: false })
.build();
const schemaValidator = new SchemaValidator(schema);Encrypt sensitive preferences:
import { AESEncryptionService } from '@hyperpolymath/preference-injector';
const encryptionService = new AESEncryptionService('your-secret-password');
injector.setEncryptionService(encryptionService);
// Store encrypted
await injector.set('apiKey', 'secret-key', { encrypt: true });
// Retrieve and decrypt
const apiKey = await injector.get('apiKey', { decrypt: true });Enable caching for better performance:
const injector = new PreferenceInjector({
providers: [provider],
enableCache: true,
cacheTTL: 3600000, // 1 hour
});Track all preference operations:
const injector = new PreferenceInjector({
providers: [provider],
enableAudit: true,
});
// Get audit log
const auditLogger = injector.getAuditLogger();
const entries = auditLogger.getEntries();Use preferences in React applications:
import { PreferenceProvider, usePreference } from '@hyperpolymath/preference-injector';
function App() {
return (
<PreferenceProvider injector={injector}>
<ThemeToggle />
</PreferenceProvider>
);
}
function ThemeToggle() {
const [theme, setTheme, loading] = usePreference<string>('theme', 'light');
if (loading) return <div>Loading...</div>;
return (
<button onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}>
Current: {theme}
</button>
);
}Add preference management to Express applications:
import express from 'express';
import {
preferenceMiddleware,
createPreferenceRouter,
} from '@hyperpolymath/preference-injector';
const app = express();
// Attach preferences to requests
app.use(preferenceMiddleware({ injector }));
// Add REST API
app.use('/api', createPreferenceRouter(injector));
// Use in routes
app.get('/config', async (req, res) => {
const value = await req.getPreference('setting');
res.json({ value });
});Manage preferences from the command line:
= Get a preference
preference-injector get theme
= Set a preference
preference-injector set theme dark
= List all preferences
preference-injector -f config.json list
= Delete a preference
preference-injector delete old-key
= Clear all preferences
preference-injector clearVersion and migrate preference schemas:
import { MigrationManager, createMigration } from '@hyperpolymath/preference-injector';
const manager = new MigrationManager();
manager.register(
createMigration(
1,
'rename-theme-to-color-scheme',
async (prefs) => {
// Migration logic
return prefs;
},
async (prefs) => {
// Rollback logic
return prefs;
}
)
);
await manager.migrateToLatest(preferences, 0);Check the [examples](./examples) directory for more usage examples:
-
[Basic Usage](./examples/basic-usage.ts)
-
[React Integration](./examples/react-example.tsx)
-
[Express Integration](./examples/express-example.ts)
Contributions are welcome! Please see [CONTRIBUTING.md](./CONTRIBUTING.md) for guidelines.