Skip to content

Commit cca90e5

Browse files
Jonathan D.A. Jewellclaude
andcommitted
fix: Restore original README content
The previous RSR standardization commit accidentally replaced the full README content with a minimal template. This restores the original project documentation. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 21a59a1 commit cca90e5

1 file changed

Lines changed: 301 additions & 53 deletions

File tree

README.adoc

Lines changed: 301 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,76 +1,324 @@
1-
= preference-injector
2-
Jonathan D.A. Jewell <jonathan.jewell@gmail.com>
3-
:toc: macro
4-
:icons: font
5-
:source-highlighter: rouge
6-
:experimental:
7-
:url-github: https://github.com/hyperpolymath/preference-injector
8-
:url-gitlab: https://gitlab.com/hyperpolymath/preference-injector
9-
:url-bitbucket: https://bitbucket.org/hyperpolymath/preference-injector
10-
:url-codeberg: https://codeberg.org/hyperpolymath/preference-injector
1+
= Preference Injector
112

12-
User preference injection for testing
3+
A powerful, type-safe preference injection system for dynamic configuration management in Node.js and TypeScript applications.
134

14-
image:https://img.shields.io/badge/RSR-Certified-gold[RSR Certified]
15-
image:https://img.shields.io/badge/License-AGPL%20v3-blue[License]
5+
== Features
166

17-
toc::[]
7+
- *Multiple Providers*: File-based, environment variables, API, and in-memory storage
8+
- *Priority System*: Resolve conflicts between providers using customizable strategies
9+
- *Type Safety*: Full TypeScript support with generic type helpers
10+
- *Caching*: LRU and TTL caching strategies for performance
11+
- *Validation*: Schema-based and custom validation rules
12+
- *Encryption*: AES-256-GCM encryption for sensitive preferences
13+
- *Audit Logging*: Track all preference operations
14+
- *Migrations*: Version and migrate preference schemas
15+
- *React Integration*: Hooks and context providers
16+
- *Express Middleware*: RESTful API and request helpers
17+
- *CLI Tool*: Command-line interface for preference management
1818

19-
== Overview
19+
== Installation
2020

21-
preference-injector is part of the link:https://rhodium.sh[Rhodium Standard] (RSR) ecosystem.
21+
```bash
22+
npm install @hyperpolymath/preference-injector
23+
```
2224

23-
Domain: *software-development*
25+
== Quick Start
2426

25-
== Installation
27+
```typescript
28+
import { PreferenceInjector, MemoryProvider } from '@hyperpolymath/preference-injector';
2629

27-
[source,bash]
28-
----
29-
# Clone from GitHub (primary)
30-
git clone {url-github}
30+
// Create an injector with an in-memory provider
31+
const injector = new PreferenceInjector({
32+
providers: [new MemoryProvider()],
33+
});
3134

32-
# Or from mirrors
33-
git clone {url-gitlab}
34-
git clone {url-codeberg}
35-
----
35+
await injector.initialize();
3636

37-
== RSR Stack
37+
// Set preferences
38+
await injector.set('theme', 'dark');
39+
await injector.set('fontSize', 14);
3840

39-
This project follows RSR conventions:
41+
// Get preferences
42+
const theme = await injector.get('theme');
43+
console.log('Theme:', theme); // 'dark'
4044

41-
* ✅ ReScript for frontend/logic
42-
* ✅ Deno for JS runtime
43-
* ✅ WASM for performance-critical code
44-
* ✅ Rust/OCaml/Haskell for systems/proofs
45-
* ✅ Guile/Scheme for configuration
46-
* ❌ No TypeScript
47-
* ❌ No Go
48-
* ❌ No npm
45+
// Get with type safety
46+
const fontSize = await injector.getTyped<number>('fontSize');
47+
console.log('Font Size:', fontSize); // 14
48+
```
4949

50-
== Mirrors
50+
== Providers
5151

52-
[cols="1,2"]
53-
|===
54-
| Platform | URL
52+
=== Memory Provider
5553

56-
| GitHub (primary) | {url-github}
57-
| GitLab | {url-gitlab}
58-
| Bitbucket | {url-bitbucket}
59-
| Codeberg | {url-codeberg}
60-
|===
54+
In-memory storage for runtime preferences:
6155

62-
== License
56+
```typescript
57+
import { MemoryProvider, PreferencePriority } from '@hyperpolymath/preference-injector';
58+
59+
const provider = new MemoryProvider(PreferencePriority.NORMAL);
60+
```
61+
62+
=== File Provider
63+
64+
JSON or .env file-based storage:
65+
66+
```typescript
67+
import { FileProvider } from '@hyperpolymath/preference-injector';
68+
69+
const provider = new FileProvider({
70+
filePath: './config.json',
71+
priority: PreferencePriority.NORMAL,
72+
watchForChanges: true,
73+
format: 'json', // or 'env'
74+
});
75+
```
76+
77+
=== Environment Provider
78+
79+
Environment variable integration:
80+
81+
```typescript
82+
import { EnvProvider } from '@hyperpolymath/preference-injector';
83+
84+
const provider = new EnvProvider({
85+
prefix: 'APP_',
86+
priority: PreferencePriority.HIGHEST,
87+
parseValues: true,
88+
});
89+
```
90+
91+
=== API Provider
92+
93+
Remote configuration service:
94+
95+
```typescript
96+
import { ApiProvider } from '@hyperpolymath/preference-injector';
97+
98+
const provider = new ApiProvider({
99+
baseUrl: 'https://config.example.com',
100+
apiKey: 'your-api-key',
101+
priority: PreferencePriority.NORMAL,
102+
timeout: 5000,
103+
retries: 3,
104+
});
105+
```
106+
107+
== Multi-Provider Setup
108+
109+
Use multiple providers with automatic conflict resolution:
110+
111+
```typescript
112+
const injector = new PreferenceInjector({
113+
providers: [
114+
new EnvProvider({ priority: PreferencePriority.HIGHEST }),
115+
new FileProvider({ filePath: './config.json', priority: PreferencePriority.NORMAL }),
116+
new MemoryProvider(PreferencePriority.LOW),
117+
],
118+
conflictResolution: ConflictResolution.HIGHEST_PRIORITY,
119+
});
120+
```
121+
122+
== Validation
123+
124+
Add validation rules to ensure preference values are valid:
125+
126+
```typescript
127+
import { CommonValidationRules } from '@hyperpolymath/preference-injector';
128+
129+
const validator = injector.getValidator();
130+
131+
// Add built-in validation rules
132+
validator.addRule('email', CommonValidationRules.email());
133+
validator.addRule('age', CommonValidationRules.numberRange(0, 150));
134+
validator.addRule('username', CommonValidationRules.stringLength(3, 20));
135+
136+
// Set with validation
137+
await injector.set('email', 'user@example.com', { validate: true });
138+
```
139+
140+
== Schema Validation
141+
142+
Define schemas for your preferences:
143+
144+
```typescript
145+
import { SchemaBuilder } from '@hyperpolymath/preference-injector';
146+
147+
const schema = new SchemaBuilder()
148+
.string('apiUrl', { required: true, pattern: /^https?:\/\// })
149+
.number('timeout', { min: 0, max: 30000, default: 5000 })
150+
.boolean('debug', { default: false })
151+
.build();
152+
153+
const schemaValidator = new SchemaValidator(schema);
154+
```
155+
156+
== Encryption
157+
158+
Encrypt sensitive preferences:
159+
160+
```typescript
161+
import { AESEncryptionService } from '@hyperpolymath/preference-injector';
162+
163+
const encryptionService = new AESEncryptionService('your-secret-password');
164+
injector.setEncryptionService(encryptionService);
165+
166+
// Store encrypted
167+
await injector.set('apiKey', 'secret-key', { encrypt: true });
168+
169+
// Retrieve and decrypt
170+
const apiKey = await injector.get('apiKey', { decrypt: true });
171+
```
172+
173+
== Caching
174+
175+
Enable caching for better performance:
63176

64-
Licensed under AGPL-3.0-or-later OR LicenseRef-Palimpsest-0.5.
177+
```typescript
178+
const injector = new PreferenceInjector({
179+
providers: [provider],
180+
enableCache: true,
181+
cacheTTL: 3600000, // 1 hour
182+
});
183+
```
65184

66-
See link:LICENSE[LICENSE] for details.
185+
== Audit Logging
186+
187+
Track all preference operations:
188+
189+
```typescript
190+
const injector = new PreferenceInjector({
191+
providers: [provider],
192+
enableAudit: true,
193+
});
194+
195+
// Get audit log
196+
const auditLogger = injector.getAuditLogger();
197+
const entries = auditLogger.getEntries();
198+
```
199+
200+
== React Integration
201+
202+
Use preferences in React applications:
203+
204+
```tsx
205+
import { PreferenceProvider, usePreference } from '@hyperpolymath/preference-injector';
206+
207+
function App() {
208+
return (
209+
<PreferenceProvider injector={injector}>
210+
<ThemeToggle />
211+
</PreferenceProvider>
212+
);
213+
}
214+
215+
function ThemeToggle() {
216+
const [theme, setTheme, loading] = usePreference<string>('theme', 'light');
217+
218+
if (loading) return <div>Loading...</div>;
219+
220+
return (
221+
<button onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}>
222+
Current: {theme}
223+
</button>
224+
);
225+
}
226+
```
227+
228+
== Express Integration
229+
230+
Add preference management to Express applications:
231+
232+
```typescript
233+
import express from 'express';
234+
import {
235+
preferenceMiddleware,
236+
createPreferenceRouter,
237+
} from '@hyperpolymath/preference-injector';
238+
239+
const app = express();
240+
241+
// Attach preferences to requests
242+
app.use(preferenceMiddleware({ injector }));
243+
244+
// Add REST API
245+
app.use('/api', createPreferenceRouter(injector));
246+
247+
// Use in routes
248+
app.get('/config', async (req, res) => {
249+
const value = await req.getPreference('setting');
250+
res.json({ value });
251+
});
252+
```
253+
254+
== CLI Tool
255+
256+
Manage preferences from the command line:
257+
258+
```bash
259+
= Get a preference
260+
preference-injector get theme
261+
262+
= Set a preference
263+
preference-injector set theme dark
264+
265+
= List all preferences
266+
preference-injector -f config.json list
267+
268+
= Delete a preference
269+
preference-injector delete old-key
270+
271+
= Clear all preferences
272+
preference-injector clear
273+
```
274+
275+
== Migrations
276+
277+
Version and migrate preference schemas:
278+
279+
```typescript
280+
import { MigrationManager, createMigration } from '@hyperpolymath/preference-injector';
281+
282+
const manager = new MigrationManager();
283+
284+
manager.register(
285+
createMigration(
286+
1,
287+
'rename-theme-to-color-scheme',
288+
async (prefs) => {
289+
// Migration logic
290+
return prefs;
291+
},
292+
async (prefs) => {
293+
// Rollback logic
294+
return prefs;
295+
}
296+
)
297+
);
298+
299+
await manager.migrateToLatest(preferences, 0);
300+
```
301+
302+
== API Documentation
303+
304+
For detailed API documentation, see [API.md](./docs/API.md).
305+
306+
== Examples
307+
308+
Check the [examples](./examples) directory for more usage examples:
309+
310+
- [Basic Usage](./examples/basic-usage.ts)
311+
- [React Integration](./examples/react-example.tsx)
312+
- [Express Integration](./examples/express-example.ts)
67313

68314
== Contributing
69315

70-
See link:CONTRIBUTING.adoc[CONTRIBUTING.adoc].
316+
Contributions are welcome! Please see [CONTRIBUTING.md](./CONTRIBUTING.md) for guidelines.
317+
318+
== License
319+
320+
MIT
71321

72-
== Metadata
322+
== Changelog
73323

74-
* Domain: software-development
75-
* Framework: RSR (Rhodium Standard Repository)
76-
* Dublin Core: link:.well-known/dc.xml[.well-known/dc.xml]
324+
See [CHANGELOG.md](./CHANGELOG.md) for release history.

0 commit comments

Comments
 (0)