@arikajs/config 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,418 @@
1
+ import * as fs from 'fs';
2
+ import * as path from 'path';
3
+ import { createRequire } from 'module';
4
+ const localRequire = createRequire(import.meta.url);
5
+ // ─── Repository ─────────────────────────────────────────────────────────────
6
+ export class Repository {
7
+ config = {};
8
+ booted = false;
9
+ // Feature 1: Config Caching
10
+ flatCache = new Map();
11
+ cacheBuilt = false;
12
+ // Feature 2: Schema Validation
13
+ schema = null;
14
+ // Feature 4: Change Listeners
15
+ listeners = new Map();
16
+ globalListeners = [];
17
+ // Feature 6: Encrypted Config
18
+ decrypter = null;
19
+ constructor(initialConfig = {}) {
20
+ this.config = { ...initialConfig };
21
+ }
22
+ // ─── Loading ────────────────────────────────────────────────────────────
23
+ /**
24
+ * Load configuration files from the config directory.
25
+ */
26
+ loadConfigDirectory(configPath, environment) {
27
+ if (this.booted) {
28
+ throw new Error('Configuration cannot be modified after boot.');
29
+ }
30
+ if (!fs.existsSync(configPath)) {
31
+ return;
32
+ }
33
+ const files = fs.readdirSync(configPath);
34
+ // Feature 3: Environment-based Merging
35
+ // First load base configs (e.g., database.js)
36
+ // Then overlay env-specific (e.g., database.production.js)
37
+ const env = environment || process.env.NODE_ENV || 'development';
38
+ const baseFiles = files.filter((file) => this.isConfigFile(file) && !this.isEnvSpecificFile(file));
39
+ const envFiles = files.filter((file) => this.isConfigFile(file) && file.includes(`.${env}.`));
40
+ // Load base configs first
41
+ for (const file of baseFiles) {
42
+ this.loadFile(configPath, file);
43
+ }
44
+ // Then overlay environment-specific configs
45
+ for (const file of envFiles) {
46
+ this.loadFile(configPath, file, true);
47
+ }
48
+ }
49
+ isConfigFile(file) {
50
+ return (file.endsWith('.js') ||
51
+ file.endsWith('.ts') ||
52
+ file.endsWith('.cjs') ||
53
+ file.endsWith('.mjs'));
54
+ }
55
+ isEnvSpecificFile(file) {
56
+ const envPatterns = [
57
+ '.development.',
58
+ '.production.',
59
+ '.staging.',
60
+ '.testing.',
61
+ '.local.',
62
+ ];
63
+ return envPatterns.some((p) => file.includes(p));
64
+ }
65
+ loadFile(configPath, file, isOverlay = false) {
66
+ const filePath = path.join(configPath, file);
67
+ // Extract base config name (e.g., "database" from "database.production.js")
68
+ const parts = path.basename(file, path.extname(file)).split('.');
69
+ const configName = parts[0];
70
+ try {
71
+ let configValue;
72
+ try {
73
+ const module = localRequire(filePath);
74
+ configValue = module.default || module;
75
+ }
76
+ catch {
77
+ // ESM fallback — silently skip
78
+ }
79
+ if (typeof configValue === 'object' && configValue !== null) {
80
+ if (isOverlay && this.config[configName]) {
81
+ // Deep merge for env overlays
82
+ this.config[configName] = this.deepMerge(this.config[configName], configValue);
83
+ }
84
+ else {
85
+ this.config[configName] = {
86
+ ...this.config[configName],
87
+ ...configValue,
88
+ };
89
+ }
90
+ }
91
+ }
92
+ catch {
93
+ // Silently skip files that can't be loaded
94
+ }
95
+ }
96
+ // ─── Get / Set / Has ────────────────────────────────────────────────────
97
+ /**
98
+ * Get a configuration value using dot notation.
99
+ * Uses flat cache for O(1) lookup when booted.
100
+ */
101
+ get(key, defaultValue) {
102
+ // Feature 1: Use flat cache after boot for O(1)
103
+ if (this.cacheBuilt) {
104
+ const cached = this.flatCache.get(key);
105
+ if (cached !== undefined) {
106
+ // Feature 6: Auto-decrypt encrypted values
107
+ if (typeof cached === 'string' && cached.startsWith('enc:')) {
108
+ return this.decrypt(cached);
109
+ }
110
+ return cached;
111
+ }
112
+ return defaultValue;
113
+ }
114
+ // Pre-boot: walk the tree
115
+ const keys = key.split('.');
116
+ let value = this.config;
117
+ for (const k of keys) {
118
+ if (value === undefined || value === null) {
119
+ return defaultValue;
120
+ }
121
+ value = value[k];
122
+ }
123
+ const result = value !== undefined ? value : defaultValue;
124
+ // Feature 6: Auto-decrypt encrypted values
125
+ if (typeof result === 'string' && result.startsWith('enc:')) {
126
+ return this.decrypt(result);
127
+ }
128
+ return result;
129
+ }
130
+ /**
131
+ * Check if a configuration key exists.
132
+ */
133
+ has(key) {
134
+ if (this.cacheBuilt) {
135
+ return this.flatCache.has(key);
136
+ }
137
+ return this.get(key) !== undefined;
138
+ }
139
+ /**
140
+ * Set a configuration value using dot notation.
141
+ */
142
+ set(key, value) {
143
+ if (this.booted) {
144
+ throw new Error('Configuration cannot be modified after boot.');
145
+ }
146
+ const oldValue = this.get(key);
147
+ const keys = key.split('.');
148
+ let current = this.config;
149
+ for (let i = 0; i < keys.length - 1; i++) {
150
+ const k = keys[i];
151
+ if (!(k in current) ||
152
+ typeof current[k] !== 'object' ||
153
+ current[k] === null) {
154
+ current[k] = {};
155
+ }
156
+ current = current[k];
157
+ }
158
+ current[keys[keys.length - 1]] = value;
159
+ // Feature 4: Notify change listeners
160
+ this.notifyListeners(key, value, oldValue);
161
+ }
162
+ /**
163
+ * Get all configuration.
164
+ */
165
+ all() {
166
+ return { ...this.config };
167
+ }
168
+ // ─── Boot Lifecycle ─────────────────────────────────────────────────────
169
+ /**
170
+ * Mark the repository as booted (read-only).
171
+ * Builds the flat cache and deep-freezes the config for immutability.
172
+ */
173
+ markAsBooted() {
174
+ // Feature 2: Validate schema before boot
175
+ if (this.schema) {
176
+ const errors = this.validateSchema();
177
+ if (errors.length > 0) {
178
+ const messages = errors.map((e) => ` - ${e.key}: ${e.message}`).join('\n');
179
+ throw new Error(`Configuration validation failed:\n${messages}`);
180
+ }
181
+ }
182
+ // Feature 1: Build flat cache
183
+ this.buildFlatCache();
184
+ // Feature 5: Deep freeze
185
+ this.deepFreeze(this.config);
186
+ this.booted = true;
187
+ }
188
+ /**
189
+ * Check if the repository has been booted.
190
+ */
191
+ isBooted() {
192
+ return this.booted;
193
+ }
194
+ // ─── Feature 1: Config Caching ──────────────────────────────────────────
195
+ /**
196
+ * Build a flat Map of all dot-notation keys for O(1) lookups.
197
+ */
198
+ buildFlatCache(obj, prefix) {
199
+ const target = obj || this.config;
200
+ const pre = prefix ? `${prefix}.` : '';
201
+ for (const key of Object.keys(target)) {
202
+ const fullKey = `${pre}${key}`;
203
+ const value = target[key];
204
+ this.flatCache.set(fullKey, value);
205
+ if (typeof value === 'object' &&
206
+ value !== null &&
207
+ !Array.isArray(value)) {
208
+ this.buildFlatCache(value, fullKey);
209
+ }
210
+ }
211
+ if (!prefix) {
212
+ this.cacheBuilt = true;
213
+ }
214
+ }
215
+ // ─── Feature 2: Schema Validation ───────────────────────────────────────
216
+ /**
217
+ * Define a validation schema for the configuration.
218
+ */
219
+ defineSchema(schema) {
220
+ this.schema = schema;
221
+ return this;
222
+ }
223
+ /**
224
+ * Validate the current config against the defined schema.
225
+ */
226
+ validate() {
227
+ if (!this.schema)
228
+ return [];
229
+ return this.validateSchema();
230
+ }
231
+ validateSchema(schema, prefix) {
232
+ const errors = [];
233
+ const rules = schema || this.schema;
234
+ if (!rules)
235
+ return errors;
236
+ for (const [key, rule] of Object.entries(rules)) {
237
+ const fullKey = prefix ? `${prefix}.${key}` : key;
238
+ const value = this.get(fullKey);
239
+ // Handle nested schema via 'children'
240
+ if (rule.children) {
241
+ errors.push(...this.validateSchema(rule.children, fullKey));
242
+ continue;
243
+ }
244
+ const r = rule;
245
+ // Required check
246
+ if (r.required && (value === undefined || value === null)) {
247
+ errors.push({
248
+ key: fullKey,
249
+ message: r.message || `'${fullKey}' is required but not set.`,
250
+ });
251
+ continue;
252
+ }
253
+ // Skip further checks if value is undefined and not required
254
+ if (value === undefined || value === null)
255
+ continue;
256
+ // Type check
257
+ if (r.type) {
258
+ const actualType = Array.isArray(value) ? 'array' : typeof value;
259
+ if (actualType !== r.type) {
260
+ errors.push({
261
+ key: fullKey,
262
+ message: r.message ||
263
+ `'${fullKey}' must be of type '${r.type}', got '${actualType}'.`,
264
+ });
265
+ }
266
+ }
267
+ // Enum check
268
+ if (r.enum && !r.enum.includes(value)) {
269
+ errors.push({
270
+ key: fullKey,
271
+ message: r.message ||
272
+ `'${fullKey}' must be one of [${r.enum.join(', ')}], got '${value}'.`,
273
+ });
274
+ }
275
+ // Min/Max for numbers
276
+ if (r.type === 'number' && typeof value === 'number') {
277
+ if (r.min !== undefined && value < r.min) {
278
+ errors.push({
279
+ key: fullKey,
280
+ message: r.message ||
281
+ `'${fullKey}' must be >= ${r.min}, got ${value}.`,
282
+ });
283
+ }
284
+ if (r.max !== undefined && value > r.max) {
285
+ errors.push({
286
+ key: fullKey,
287
+ message: r.message ||
288
+ `'${fullKey}' must be <= ${r.max}, got ${value}.`,
289
+ });
290
+ }
291
+ }
292
+ // Min/Max for string length
293
+ if (r.type === 'string' && typeof value === 'string') {
294
+ if (r.min !== undefined && value.length < r.min) {
295
+ errors.push({
296
+ key: fullKey,
297
+ message: r.message ||
298
+ `'${fullKey}' must have at least ${r.min} characters.`,
299
+ });
300
+ }
301
+ if (r.max !== undefined && value.length > r.max) {
302
+ errors.push({
303
+ key: fullKey,
304
+ message: r.message ||
305
+ `'${fullKey}' must have at most ${r.max} characters.`,
306
+ });
307
+ }
308
+ }
309
+ // Pattern check
310
+ if (r.pattern && typeof value === 'string' && !r.pattern.test(value)) {
311
+ errors.push({
312
+ key: fullKey,
313
+ message: r.message ||
314
+ `'${fullKey}' does not match the required pattern.`,
315
+ });
316
+ }
317
+ }
318
+ return errors;
319
+ }
320
+ // ─── Feature 3: Environment Merging (handled in loadConfigDirectory) ────
321
+ // ─── Feature 4: Config Change Listeners ─────────────────────────────────
322
+ /**
323
+ * Register a listener for changes to a specific config key.
324
+ */
325
+ onChange(key, listener) {
326
+ if (!this.listeners.has(key)) {
327
+ this.listeners.set(key, []);
328
+ }
329
+ this.listeners.get(key).push(listener);
330
+ return this;
331
+ }
332
+ /**
333
+ * Register a global listener for ALL config changes.
334
+ */
335
+ onAnyChange(listener) {
336
+ this.globalListeners.push(listener);
337
+ return this;
338
+ }
339
+ notifyListeners(key, newValue, oldValue) {
340
+ // Key-specific listeners
341
+ const keyListeners = this.listeners.get(key);
342
+ if (keyListeners) {
343
+ for (const listener of keyListeners) {
344
+ listener(key, newValue, oldValue);
345
+ }
346
+ }
347
+ // Wildcard: notify listeners for parent keys too
348
+ // e.g. changing 'database.host' should notify 'database' listeners
349
+ const parts = key.split('.');
350
+ for (let i = parts.length - 1; i > 0; i--) {
351
+ const parentKey = parts.slice(0, i).join('.');
352
+ const parentListeners = this.listeners.get(parentKey);
353
+ if (parentListeners) {
354
+ for (const listener of parentListeners) {
355
+ listener(key, newValue, oldValue);
356
+ }
357
+ }
358
+ }
359
+ // Global listeners
360
+ for (const listener of this.globalListeners) {
361
+ listener(key, newValue, oldValue);
362
+ }
363
+ }
364
+ // ─── Feature 5: Deep Freeze ─────────────────────────────────────────────
365
+ /**
366
+ * Recursively freeze an object to prevent any mutations.
367
+ */
368
+ deepFreeze(obj) {
369
+ if (obj === null || typeof obj !== 'object')
370
+ return obj;
371
+ Object.freeze(obj);
372
+ for (const key of Object.keys(obj)) {
373
+ const value = obj[key];
374
+ if (typeof value === 'object' && value !== null && !Object.isFrozen(value)) {
375
+ this.deepFreeze(value);
376
+ }
377
+ }
378
+ return obj;
379
+ }
380
+ // ─── Feature 6: Encrypted Config Values ─────────────────────────────────
381
+ /**
382
+ * Set a decrypter function for auto-decrypting `enc:` prefixed values.
383
+ */
384
+ setDecrypter(fn) {
385
+ this.decrypter = fn;
386
+ return this;
387
+ }
388
+ decrypt(value) {
389
+ const encrypted = value.substring(4); // Remove 'enc:' prefix
390
+ if (this.decrypter) {
391
+ return this.decrypter(encrypted);
392
+ }
393
+ // If no decrypter is set, return the raw encrypted string
394
+ return encrypted;
395
+ }
396
+ // ─── Utilities ──────────────────────────────────────────────────────────
397
+ /**
398
+ * Deep merge two objects. Source values override target values.
399
+ */
400
+ deepMerge(target, source) {
401
+ const result = { ...target };
402
+ for (const key of Object.keys(source)) {
403
+ if (source[key] &&
404
+ typeof source[key] === 'object' &&
405
+ !Array.isArray(source[key]) &&
406
+ result[key] &&
407
+ typeof result[key] === 'object' &&
408
+ !Array.isArray(result[key])) {
409
+ result[key] = this.deepMerge(result[key], source[key]);
410
+ }
411
+ else {
412
+ result[key] = source[key];
413
+ }
414
+ }
415
+ return result;
416
+ }
417
+ }
418
+ //# sourceMappingURL=Repository.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Repository.js","sourceRoot":"","sources":["../src/Repository.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import { Repository } from './Repository.js';
2
+ /**
3
+ * Set the global configuration repository.
4
+ */
5
+ export declare function setConfigRepository(repo: Repository): void;
6
+ /**
7
+ * Get/Set configuration values.
8
+ */
9
+ export declare function config<T = any>(key?: string, defaultValue?: T): T | Repository | any;
10
+ /**
11
+ * Get an environment variable.
12
+ */
13
+ export declare function env<T = any>(key: string, defaultValue?: T): T;
@@ -0,0 +1,27 @@
1
+ import { EnvLoader } from './EnvLoader.js';
2
+ let repository = null;
3
+ /**
4
+ * Set the global configuration repository.
5
+ */
6
+ export function setConfigRepository(repo) {
7
+ repository = repo;
8
+ }
9
+ /**
10
+ * Get/Set configuration values.
11
+ */
12
+ export function config(key, defaultValue) {
13
+ if (key === undefined) {
14
+ return repository;
15
+ }
16
+ if (!repository) {
17
+ return defaultValue;
18
+ }
19
+ return repository.get(key, defaultValue);
20
+ }
21
+ /**
22
+ * Get an environment variable.
23
+ */
24
+ export function env(key, defaultValue) {
25
+ return EnvLoader.get(key, defaultValue);
26
+ }
27
+ //# sourceMappingURL=helpers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers.js","sourceRoot":"","sources":["../src/helpers.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE3C,IAAI,UAAU,GAAsB,IAAI,CAAC;AAEzC;;GAEG;AACH,MAAM,UAAU,mBAAmB,CAAC,IAAgB;IAChD,UAAU,GAAG,IAAI,CAAC;AACtB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,MAAM,CAAU,GAAY,EAAE,YAAgB;IAC1D,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;QACpB,OAAO,UAAU,CAAC;IACtB,CAAC;IAED,IAAI,CAAC,UAAU,EAAE,CAAC;QACd,OAAO,YAAY,CAAC;IACxB,CAAC;IAED,OAAO,UAAU,CAAC,GAAG,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC;AAC7C,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,GAAG,CAAU,GAAW,EAAE,YAAgB;IACtD,OAAO,SAAS,CAAC,GAAG,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC;AAC5C,CAAC"}
@@ -0,0 +1,4 @@
1
+ export * from './Repository.js';
2
+ export * from './EnvLoader.js';
3
+ export * from './helpers.js';
4
+ export type { SchemaRule, ConfigSchema, ValidationError, ConfigChangeListener, } from './Repository.js';
package/dist/index.js ADDED
@@ -0,0 +1,4 @@
1
+ export * from './Repository.js';
2
+ export * from './EnvLoader.js';
3
+ export * from './helpers.js';
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC"}
package/package.json ADDED
@@ -0,0 +1,33 @@
1
+ {
2
+ "name": "@arikajs/config",
3
+ "version": "0.0.5",
4
+ "description": "Premium configuration management for ArikaJS.",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "main": "dist/index.js",
8
+ "types": "dist/index.d.ts",
9
+ "scripts": {
10
+ "build": "tsc -p tsconfig.json",
11
+ "clean": "rm -rf dist",
12
+ "test": "npx tsx --test tests/**/*.test.ts",
13
+ "dev": "tsc -p tsconfig.json --watch"
14
+ },
15
+ "dependencies": {
16
+ "dotenv": "^16.4.5"
17
+ },
18
+ "devDependencies": {
19
+ "@types/node": "^20.11.24",
20
+ "typescript": "^5.3.3",
21
+ "tsx": "^4.7.1"
22
+ },
23
+ "author": "Prakash Tank",
24
+ "repository": {
25
+ "type": "git",
26
+ "url": "git+https://github.com/ArikaJs/arikajs.git",
27
+ "directory": "packages/config"
28
+ },
29
+ "bugs": {
30
+ "url": "https://github.com/ArikaJs/arikajs/issues"
31
+ },
32
+ "homepage": "https://github.com/ArikaJs/arikajs/tree/main/packages/config#readme"
33
+ }
@@ -0,0 +1,51 @@
1
+
2
+ import * as dotenv from 'dotenv';
3
+ import * as fs from 'fs';
4
+ import * as path from 'path';
5
+
6
+ export class EnvLoader {
7
+ /**
8
+ * Load environment variables from the given path.
9
+ */
10
+ public static load(basePath: string): void {
11
+ const envPath = path.join(basePath, '.env');
12
+
13
+ if (fs.existsSync(envPath)) {
14
+ dotenv.config({ path: envPath, override: true });
15
+ }
16
+
17
+ // Load .env.example if .env doesn't exist (optional, mostly for local dev)
18
+ const examplePath = path.join(basePath, '.env.example');
19
+ if (!fs.existsSync(envPath) && fs.existsSync(examplePath)) {
20
+ dotenv.config({ path: examplePath, override: true });
21
+ }
22
+ }
23
+
24
+ /**
25
+ * Get an environment variable with intelligent type casting.
26
+ */
27
+ public static get<T = any>(key: string, defaultValue?: T): T {
28
+ const value = process.env[key];
29
+
30
+ if (value === undefined) {
31
+ return defaultValue as T;
32
+ }
33
+
34
+ switch (value.toLowerCase()) {
35
+ case 'true':
36
+ case '(true)':
37
+ return true as any;
38
+ case 'false':
39
+ case '(false)':
40
+ return false as any;
41
+ case 'empty':
42
+ case '(empty)':
43
+ return '' as any;
44
+ case 'null':
45
+ case '(null)':
46
+ return null as any;
47
+ }
48
+
49
+ return value as any;
50
+ }
51
+ }