@abdokouta/react-config 1.0.1 → 1.0.2
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.
- package/dist/{index.d.mts → index.d.cts} +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +46 -17
- package/.examples/01-basic-usage.ts +0 -291
- package/.examples/02-env-helper.ts +0 -282
- package/.examples/README.md +0 -297
- package/.prettierrc.js +0 -1
- package/__tests__/config.module.test.ts +0 -244
- package/__tests__/drivers/env.driver.test.ts +0 -259
- package/__tests__/services/config.service.test.ts +0 -335
- package/__tests__/setup.d.ts +0 -11
- package/__tests__/vitest.setup.ts +0 -30
- package/eslint.config.js +0 -13
- package/src/config.module.ts +0 -152
- package/src/constants/index.ts +0 -5
- package/src/constants/tokens.constant.ts +0 -38
- package/src/drivers/env.driver.ts +0 -208
- package/src/drivers/file.driver.ts +0 -82
- package/src/drivers/index.ts +0 -6
- package/src/index.ts +0 -93
- package/src/interfaces/config-driver.interface.ts +0 -30
- package/src/interfaces/config-module-options.interface.ts +0 -84
- package/src/interfaces/config-service.interface.ts +0 -71
- package/src/interfaces/index.ts +0 -8
- package/src/interfaces/vite-config-plugin-options.interface.ts +0 -56
- package/src/plugins/index.ts +0 -5
- package/src/plugins/vite.plugin.ts +0 -118
- package/src/services/config.service.ts +0 -172
- package/src/services/index.ts +0 -5
- package/src/utils/define-config.util.ts +0 -35
- package/src/utils/get-nested-value.util.ts +0 -53
- package/src/utils/index.ts +0 -9
- package/src/utils/load-config-file.util.ts +0 -32
- package/src/utils/scan-config-files.util.ts +0 -36
- package/tsconfig.json +0 -28
- package/tsup.config.ts +0 -105
- package/vitest.config.ts +0 -66
package/src/config.module.ts
DELETED
|
@@ -1,152 +0,0 @@
|
|
|
1
|
-
import { Module, DynamicModule } from '@abdokouta/react-di';
|
|
2
|
-
|
|
3
|
-
import { EnvDriver } from './drivers/env.driver';
|
|
4
|
-
import { FileDriver } from './drivers/file.driver';
|
|
5
|
-
import { ConfigService } from './services/config.service';
|
|
6
|
-
import type { ConfigDriver } from './interfaces/config-driver.interface';
|
|
7
|
-
import type { ConfigModuleOptions } from './interfaces/config-module-options.interface';
|
|
8
|
-
import { CONFIG_DRIVER, CONFIG_OPTIONS, CONFIG_SERVICE } from './constants/tokens.constant';
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Configuration Module
|
|
12
|
-
*
|
|
13
|
-
* Provides configuration management with multiple drivers.
|
|
14
|
-
* Similar to NestJS ConfigModule.
|
|
15
|
-
*
|
|
16
|
-
* @example
|
|
17
|
-
* ```typescript
|
|
18
|
-
* // Using environment variables (default)
|
|
19
|
-
* @Module({
|
|
20
|
-
* imports: [
|
|
21
|
-
* ConfigModule.forRoot({
|
|
22
|
-
* envFilePath: '.env',
|
|
23
|
-
* isGlobal: true,
|
|
24
|
-
* }),
|
|
25
|
-
* ],
|
|
26
|
-
* })
|
|
27
|
-
* export class AppModule {}
|
|
28
|
-
* ```
|
|
29
|
-
*
|
|
30
|
-
* @example
|
|
31
|
-
* ```typescript
|
|
32
|
-
* // Using file-based configuration
|
|
33
|
-
* @Module({
|
|
34
|
-
* imports: [
|
|
35
|
-
* ConfigModule.forRoot({
|
|
36
|
-
* driver: 'file',
|
|
37
|
-
* filePattern: 'config/**\/*.config.ts',
|
|
38
|
-
* isGlobal: true,
|
|
39
|
-
* }),
|
|
40
|
-
* ],
|
|
41
|
-
* })
|
|
42
|
-
* export class AppModule {}
|
|
43
|
-
* ```
|
|
44
|
-
*/
|
|
45
|
-
@Module({})
|
|
46
|
-
export class ConfigModule {
|
|
47
|
-
/**
|
|
48
|
-
* Register configuration module with options
|
|
49
|
-
*
|
|
50
|
-
* @param options - Configuration options
|
|
51
|
-
* @returns Dynamic module
|
|
52
|
-
*/
|
|
53
|
-
static forRoot(options: ConfigModuleOptions = {}): DynamicModule {
|
|
54
|
-
const driver = this.createDriver(options);
|
|
55
|
-
|
|
56
|
-
const isGlobal = options.isGlobal ?? false;
|
|
57
|
-
|
|
58
|
-
const providers = [
|
|
59
|
-
{
|
|
60
|
-
provide: CONFIG_OPTIONS,
|
|
61
|
-
useValue: options,
|
|
62
|
-
isGlobal,
|
|
63
|
-
},
|
|
64
|
-
{
|
|
65
|
-
provide: CONFIG_DRIVER,
|
|
66
|
-
useValue: driver,
|
|
67
|
-
isGlobal,
|
|
68
|
-
},
|
|
69
|
-
ConfigService,
|
|
70
|
-
{
|
|
71
|
-
provide: CONFIG_SERVICE,
|
|
72
|
-
useExisting: ConfigService,
|
|
73
|
-
isGlobal,
|
|
74
|
-
},
|
|
75
|
-
];
|
|
76
|
-
|
|
77
|
-
return {
|
|
78
|
-
module: ConfigModule,
|
|
79
|
-
providers: providers as any,
|
|
80
|
-
exports: [ConfigService],
|
|
81
|
-
};
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* Register configuration module asynchronously
|
|
86
|
-
*
|
|
87
|
-
* @param options - Async configuration options
|
|
88
|
-
* @returns Dynamic module
|
|
89
|
-
*/
|
|
90
|
-
static async forRootAsync(
|
|
91
|
-
options: ConfigModuleOptions & {
|
|
92
|
-
useFactory?: () => Promise<ConfigModuleOptions> | ConfigModuleOptions;
|
|
93
|
-
}
|
|
94
|
-
): Promise<DynamicModule> {
|
|
95
|
-
const resolvedOptions = options.useFactory ? await options.useFactory() : options;
|
|
96
|
-
|
|
97
|
-
return this.forRoot(resolvedOptions);
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
/**
|
|
101
|
-
* Create configuration driver based on options
|
|
102
|
-
*/
|
|
103
|
-
private static createDriver(options: ConfigModuleOptions): ConfigDriver {
|
|
104
|
-
const driverType = options.driver || 'env';
|
|
105
|
-
|
|
106
|
-
switch (driverType) {
|
|
107
|
-
case 'env':
|
|
108
|
-
const envDriver = new EnvDriver({
|
|
109
|
-
envFilePath: options.envFilePath,
|
|
110
|
-
ignoreEnvFile: options.ignoreEnvFile,
|
|
111
|
-
expandVariables: options.expandVariables,
|
|
112
|
-
envPrefix: options.envPrefix,
|
|
113
|
-
globalName: options.globalName,
|
|
114
|
-
});
|
|
115
|
-
envDriver.load();
|
|
116
|
-
|
|
117
|
-
// Merge custom load function if provided
|
|
118
|
-
if (options.load) {
|
|
119
|
-
this.mergeCustomConfig(envDriver, options.load);
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
return envDriver;
|
|
123
|
-
|
|
124
|
-
case 'file':
|
|
125
|
-
const fileDriver = new FileDriver({
|
|
126
|
-
config: typeof options.load === 'object' ? options.load : undefined,
|
|
127
|
-
});
|
|
128
|
-
return fileDriver;
|
|
129
|
-
|
|
130
|
-
default:
|
|
131
|
-
throw new Error(`Unknown configuration driver: ${driverType}`);
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
/**
|
|
136
|
-
* Merge custom configuration into driver
|
|
137
|
-
*/
|
|
138
|
-
private static mergeCustomConfig(
|
|
139
|
-
driver: ConfigDriver,
|
|
140
|
-
load: Record<string, any> | (() => Record<string, any> | Promise<Record<string, any>>)
|
|
141
|
-
): void {
|
|
142
|
-
const customConfig = typeof load === 'function' ? load() : load;
|
|
143
|
-
|
|
144
|
-
if (customConfig instanceof Promise) {
|
|
145
|
-
customConfig.then((config) => {
|
|
146
|
-
Object.assign(driver.all(), config);
|
|
147
|
-
});
|
|
148
|
-
} else {
|
|
149
|
-
Object.assign(driver.all(), customConfig);
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
}
|
package/src/constants/index.ts
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Dependency Injection Tokens
|
|
3
|
-
*
|
|
4
|
-
* Used for injecting configuration dependencies.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Configuration driver token
|
|
9
|
-
*
|
|
10
|
-
* @example
|
|
11
|
-
* ```typescript
|
|
12
|
-
* @Inject(CONFIG_DRIVER)
|
|
13
|
-
* private driver: ConfigDriver
|
|
14
|
-
* ```
|
|
15
|
-
*/
|
|
16
|
-
export const CONFIG_DRIVER = Symbol('CONFIG_DRIVER');
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Configuration options token
|
|
20
|
-
*
|
|
21
|
-
* @example
|
|
22
|
-
* ```typescript
|
|
23
|
-
* @Inject(CONFIG_OPTIONS)
|
|
24
|
-
* private options: ConfigModuleOptions
|
|
25
|
-
* ```
|
|
26
|
-
*/
|
|
27
|
-
export const CONFIG_OPTIONS = Symbol('CONFIG_OPTIONS');
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Configuration service token
|
|
31
|
-
*
|
|
32
|
-
* @example
|
|
33
|
-
* ```typescript
|
|
34
|
-
* @Inject(CONFIG_SERVICE)
|
|
35
|
-
* private config: ConfigService
|
|
36
|
-
* ```
|
|
37
|
-
*/
|
|
38
|
-
export const CONFIG_SERVICE = Symbol('CONFIG_SERVICE');
|
|
@@ -1,208 +0,0 @@
|
|
|
1
|
-
import type { ConfigDriver } from '../interfaces/config-driver.interface';
|
|
2
|
-
import { getNestedValue, hasNestedValue } from '../utils/get-nested-value.util';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Environment Variable Configuration Driver
|
|
6
|
-
*
|
|
7
|
-
* Loads configuration from environment variables (process.env).
|
|
8
|
-
* Supports .env files via dotenv.
|
|
9
|
-
*/
|
|
10
|
-
export class EnvDriver implements ConfigDriver {
|
|
11
|
-
private config: Record<string, any> = {};
|
|
12
|
-
private loaded = false;
|
|
13
|
-
|
|
14
|
-
constructor(
|
|
15
|
-
private options: {
|
|
16
|
-
envFilePath?: string | string[];
|
|
17
|
-
ignoreEnvFile?: boolean;
|
|
18
|
-
expandVariables?: boolean;
|
|
19
|
-
envPrefix?: string | false;
|
|
20
|
-
globalName?: string; // Custom global variable name
|
|
21
|
-
} = {}
|
|
22
|
-
) {}
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Load environment variables
|
|
26
|
-
*/
|
|
27
|
-
load(): Record<string, any> {
|
|
28
|
-
if (this.loaded) {
|
|
29
|
-
console.log('[EnvDriver] Already loaded, returning cached config');
|
|
30
|
-
return this.config;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
console.log('[EnvDriver] Loading environment variables...');
|
|
34
|
-
console.log('[EnvDriver] Options:', { ...this.options });
|
|
35
|
-
|
|
36
|
-
// Load .env file if not ignored
|
|
37
|
-
if (!this.options.ignoreEnvFile) {
|
|
38
|
-
this.loadDotEnv();
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
// Get global config name (default: __APP_CONFIG__)
|
|
42
|
-
const globalName = this.options.globalName || '__APP_CONFIG__';
|
|
43
|
-
|
|
44
|
-
// Try to load from custom global variable first (browser environment)
|
|
45
|
-
if (typeof window !== 'undefined' && (window as any)[globalName]) {
|
|
46
|
-
this.config = { ...(window as any)[globalName] };
|
|
47
|
-
console.log(
|
|
48
|
-
`[EnvDriver] Loaded config from window.${globalName}:`,
|
|
49
|
-
Object.keys(this.config).length,
|
|
50
|
-
'keys'
|
|
51
|
-
);
|
|
52
|
-
}
|
|
53
|
-
// Fallback to process.env (Node.js environment or backward compatibility)
|
|
54
|
-
else if (typeof process !== 'undefined' && process.env) {
|
|
55
|
-
this.config = { ...process.env };
|
|
56
|
-
console.log(
|
|
57
|
-
'[EnvDriver] Loaded config from process.env:',
|
|
58
|
-
Object.keys(this.config).length,
|
|
59
|
-
'keys'
|
|
60
|
-
);
|
|
61
|
-
}
|
|
62
|
-
// No config source available
|
|
63
|
-
else {
|
|
64
|
-
console.warn(
|
|
65
|
-
'[EnvDriver] No config source available (neither window.' + globalName + ' nor process.env)'
|
|
66
|
-
);
|
|
67
|
-
this.config = {};
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
console.log('[EnvDriver] Initial config keys:', [
|
|
71
|
-
...Object.keys(this.config).filter((k) => k.includes('APP') || k.includes('VITE')),
|
|
72
|
-
]);
|
|
73
|
-
|
|
74
|
-
// Strip prefix if configured
|
|
75
|
-
if (this.options.envPrefix !== false) {
|
|
76
|
-
console.log('[EnvDriver] Stripping prefix...');
|
|
77
|
-
this.stripPrefix();
|
|
78
|
-
console.log('[EnvDriver] After stripPrefix, config keys:', [
|
|
79
|
-
...Object.keys(this.config).filter((k) => k.includes('APP') || k.includes('VITE')),
|
|
80
|
-
]);
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
// Expand variables if enabled
|
|
84
|
-
if (this.options.expandVariables) {
|
|
85
|
-
this.expandEnvVariables();
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
this.loaded = true;
|
|
89
|
-
console.log('[EnvDriver] Load complete. Sample values:', {
|
|
90
|
-
APP_NAME: this.config.APP_NAME,
|
|
91
|
-
VITE_APP_NAME: this.config.VITE_APP_NAME,
|
|
92
|
-
});
|
|
93
|
-
return this.config;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
/**
|
|
97
|
-
* Get configuration value
|
|
98
|
-
*/
|
|
99
|
-
get<T = any>(key: string, defaultValue?: T): T | undefined {
|
|
100
|
-
if (!this.loaded) {
|
|
101
|
-
this.load();
|
|
102
|
-
}
|
|
103
|
-
const value = getNestedValue(this.config, key, defaultValue);
|
|
104
|
-
console.log(`[EnvDriver] get("${key}", "${defaultValue}") = "${value}"`);
|
|
105
|
-
return value;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
/**
|
|
109
|
-
* Check if key exists
|
|
110
|
-
*/
|
|
111
|
-
has(key: string): boolean {
|
|
112
|
-
if (!this.loaded) {
|
|
113
|
-
this.load();
|
|
114
|
-
}
|
|
115
|
-
return hasNestedValue(this.config, key);
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
/**
|
|
119
|
-
* Get all configuration
|
|
120
|
-
*/
|
|
121
|
-
all(): Record<string, any> {
|
|
122
|
-
if (!this.loaded) {
|
|
123
|
-
this.load();
|
|
124
|
-
}
|
|
125
|
-
return { ...this.config };
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
/**
|
|
129
|
-
* Load .env file using dotenv
|
|
130
|
-
*/
|
|
131
|
-
private loadDotEnv(): void {
|
|
132
|
-
try {
|
|
133
|
-
// Try to load dotenv
|
|
134
|
-
const dotenv = require('dotenv');
|
|
135
|
-
const paths = Array.isArray(this.options.envFilePath)
|
|
136
|
-
? this.options.envFilePath
|
|
137
|
-
: [this.options.envFilePath || '.env'];
|
|
138
|
-
|
|
139
|
-
for (const path of paths) {
|
|
140
|
-
dotenv.config({ path });
|
|
141
|
-
}
|
|
142
|
-
} catch (error) {
|
|
143
|
-
// dotenv not installed, skip
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
/**
|
|
148
|
-
* Expand environment variables (e.g., ${VAR_NAME})
|
|
149
|
-
*/
|
|
150
|
-
private expandEnvVariables(): void {
|
|
151
|
-
const regex = /\$\{([^}]+)\}/g;
|
|
152
|
-
|
|
153
|
-
const expand = (value: string): string => {
|
|
154
|
-
return value.replace(regex, (_, key) => {
|
|
155
|
-
return this.config[key] || '';
|
|
156
|
-
});
|
|
157
|
-
};
|
|
158
|
-
|
|
159
|
-
for (const [key, value] of Object.entries(this.config)) {
|
|
160
|
-
if (typeof value === 'string' && value.includes('${')) {
|
|
161
|
-
this.config[key] = expand(value);
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
/**
|
|
167
|
-
* Strip environment variable prefix
|
|
168
|
-
* Auto-detects framework (Vite, Next.js) or uses custom prefix
|
|
169
|
-
*/
|
|
170
|
-
private stripPrefix(): void {
|
|
171
|
-
let prefix = this.options.envPrefix;
|
|
172
|
-
|
|
173
|
-
// Auto-detect framework prefix
|
|
174
|
-
if (prefix === 'auto' || prefix === undefined) {
|
|
175
|
-
// Check for Vite (import.meta.env exists or VITE_ variables present)
|
|
176
|
-
const hasViteVars = Object.keys(this.config).some((key) => key.startsWith('VITE_'));
|
|
177
|
-
if (hasViteVars || typeof import.meta !== 'undefined') {
|
|
178
|
-
prefix = 'VITE_';
|
|
179
|
-
}
|
|
180
|
-
// Check for Next.js (NEXT_PUBLIC_ variables present)
|
|
181
|
-
else if (Object.keys(this.config).some((key) => key.startsWith('NEXT_PUBLIC_'))) {
|
|
182
|
-
prefix = 'NEXT_PUBLIC_';
|
|
183
|
-
}
|
|
184
|
-
// No framework detected, don't strip
|
|
185
|
-
else {
|
|
186
|
-
return;
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
// Strip the prefix from all matching keys
|
|
191
|
-
if (typeof prefix === 'string' && prefix.length > 0) {
|
|
192
|
-
const newConfig: Record<string, any> = {};
|
|
193
|
-
|
|
194
|
-
for (const [key, value] of Object.entries(this.config)) {
|
|
195
|
-
if (key.startsWith(prefix)) {
|
|
196
|
-
// Add both prefixed and unprefixed versions
|
|
197
|
-
const unprefixedKey = key.substring(prefix.length);
|
|
198
|
-
newConfig[unprefixedKey] = value;
|
|
199
|
-
newConfig[key] = value; // Keep original too
|
|
200
|
-
} else {
|
|
201
|
-
newConfig[key] = value;
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
this.config = newConfig;
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
}
|
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
import type { ConfigDriver } from '@/interfaces/config-driver.interface';
|
|
2
|
-
import { getNestedValue, hasNestedValue } from '@/utils/get-nested-value.util';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* File-based Configuration Driver
|
|
6
|
-
*
|
|
7
|
-
* Loads configuration from TypeScript/JavaScript files.
|
|
8
|
-
* This is a server-side only driver. For client-side, use the Vite plugin.
|
|
9
|
-
*
|
|
10
|
-
* @see packages/pixielity/config/src/plugins/vite-config.plugin.ts
|
|
11
|
-
*/
|
|
12
|
-
export class FileDriver implements ConfigDriver {
|
|
13
|
-
private config: Record<string, any> = {};
|
|
14
|
-
private loaded = false;
|
|
15
|
-
|
|
16
|
-
constructor(
|
|
17
|
-
options: {
|
|
18
|
-
config?: Record<string, any>;
|
|
19
|
-
} = {}
|
|
20
|
-
) {
|
|
21
|
-
// Pre-loaded config from Vite plugin or server
|
|
22
|
-
if (options.config) {
|
|
23
|
-
this.config = options.config;
|
|
24
|
-
this.loaded = true;
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Load configuration
|
|
30
|
-
* Config should be pre-loaded via Vite plugin or passed in constructor
|
|
31
|
-
*/
|
|
32
|
-
async load(): Promise<Record<string, any>> {
|
|
33
|
-
if (this.loaded) {
|
|
34
|
-
return this.config;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
// If running on server (Node.js), throw error
|
|
38
|
-
const isServer =
|
|
39
|
-
typeof globalThis !== 'undefined' &&
|
|
40
|
-
typeof (globalThis as typeof globalThis & { window?: any }).window === 'undefined';
|
|
41
|
-
|
|
42
|
-
if (isServer) {
|
|
43
|
-
throw new Error(
|
|
44
|
-
'FileDriver requires pre-loaded configuration. ' +
|
|
45
|
-
'Use Vite plugin for client-side or pass config in constructor for server-side.'
|
|
46
|
-
);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
this.loaded = true;
|
|
50
|
-
return this.config;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* Get configuration value
|
|
55
|
-
*/
|
|
56
|
-
get<T = any>(key: string, defaultValue?: T): T | undefined {
|
|
57
|
-
if (!this.loaded) {
|
|
58
|
-
throw new Error('Configuration not loaded. Call load() first or use async initialization.');
|
|
59
|
-
}
|
|
60
|
-
return getNestedValue(this.config, key, defaultValue);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* Check if key exists
|
|
65
|
-
*/
|
|
66
|
-
has(key: string): boolean {
|
|
67
|
-
if (!this.loaded) {
|
|
68
|
-
throw new Error('Configuration not loaded. Call load() first or use async initialization.');
|
|
69
|
-
}
|
|
70
|
-
return hasNestedValue(this.config, key);
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* Get all configuration
|
|
75
|
-
*/
|
|
76
|
-
all(): Record<string, any> {
|
|
77
|
-
if (!this.loaded) {
|
|
78
|
-
throw new Error('Configuration not loaded. Call load() first or use async initialization.');
|
|
79
|
-
}
|
|
80
|
-
return { ...this.config };
|
|
81
|
-
}
|
|
82
|
-
}
|
package/src/drivers/index.ts
DELETED
package/src/index.ts
DELETED
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @abdokouta/config
|
|
3
|
-
*
|
|
4
|
-
* NestJS-inspired configuration management with multiple drivers for loading
|
|
5
|
-
* configuration from various sources (environment variables, files, etc.).
|
|
6
|
-
* Provides type-safe access to configuration values with support for nested
|
|
7
|
-
* properties and default values.
|
|
8
|
-
*
|
|
9
|
-
* @example
|
|
10
|
-
* Basic usage with environment variables:
|
|
11
|
-
* ```typescript
|
|
12
|
-
* import { ConfigModule, ConfigService, EnvDriver } from '@abdokouta/config';
|
|
13
|
-
* import { Module, Injectable, Inject } from '@abdokouta/react-di';
|
|
14
|
-
*
|
|
15
|
-
* @Module({
|
|
16
|
-
* imports: [
|
|
17
|
-
* ConfigModule.forRoot({
|
|
18
|
-
* driver: new EnvDriver(),
|
|
19
|
-
* }),
|
|
20
|
-
* ],
|
|
21
|
-
* })
|
|
22
|
-
* export class AppModule {}
|
|
23
|
-
*
|
|
24
|
-
* @Injectable()
|
|
25
|
-
* class DatabaseService {
|
|
26
|
-
* constructor(@Inject(ConfigService) private config: ConfigService) {}
|
|
27
|
-
*
|
|
28
|
-
* connect() {
|
|
29
|
-
* const host = this.config.get('DATABASE_HOST', 'localhost');
|
|
30
|
-
* const port = this.config.get('DATABASE_PORT', 5432);
|
|
31
|
-
* // Connect to database...
|
|
32
|
-
* }
|
|
33
|
-
* }
|
|
34
|
-
* ```
|
|
35
|
-
*
|
|
36
|
-
* @example
|
|
37
|
-
* Using file-based configuration:
|
|
38
|
-
* ```typescript
|
|
39
|
-
* import { ConfigModule, FileDriver } from '@abdokouta/config';
|
|
40
|
-
*
|
|
41
|
-
* @Module({
|
|
42
|
-
* imports: [
|
|
43
|
-
* ConfigModule.forRoot({
|
|
44
|
-
* driver: new FileDriver({
|
|
45
|
-
* path: './config/app.json',
|
|
46
|
-
* }),
|
|
47
|
-
* }),
|
|
48
|
-
* ],
|
|
49
|
-
* })
|
|
50
|
-
* export class AppModule {}
|
|
51
|
-
* ```
|
|
52
|
-
*
|
|
53
|
-
* @example
|
|
54
|
-
* Accessing nested configuration:
|
|
55
|
-
* ```typescript
|
|
56
|
-
* // config.json: { "database": { "host": "localhost", "port": 5432 } }
|
|
57
|
-
* const host = config.get('database.host');
|
|
58
|
-
* const port = config.get('database.port', 3306);
|
|
59
|
-
* ```
|
|
60
|
-
*
|
|
61
|
-
* @module @abdokouta/config
|
|
62
|
-
*/
|
|
63
|
-
|
|
64
|
-
// ============================================================================
|
|
65
|
-
// Module (DI Configuration)
|
|
66
|
-
// ============================================================================
|
|
67
|
-
export { ConfigModule } from './config.module';
|
|
68
|
-
|
|
69
|
-
// ============================================================================
|
|
70
|
-
// Core Service
|
|
71
|
-
// ============================================================================
|
|
72
|
-
export { ConfigService } from './services/config.service';
|
|
73
|
-
|
|
74
|
-
// ============================================================================
|
|
75
|
-
// Drivers
|
|
76
|
-
// ============================================================================
|
|
77
|
-
export { EnvDriver } from './drivers/env.driver';
|
|
78
|
-
export { FileDriver } from './drivers/file.driver';
|
|
79
|
-
|
|
80
|
-
// ============================================================================
|
|
81
|
-
// Interfaces
|
|
82
|
-
// ============================================================================
|
|
83
|
-
export type { ConfigDriver } from './interfaces/config-driver.interface';
|
|
84
|
-
export type { ConfigModuleOptions } from './interfaces/config-module-options.interface';
|
|
85
|
-
export type { ConfigServiceInterface } from './interfaces/config-service.interface';
|
|
86
|
-
export type { ViteConfigPluginOptions } from './interfaces/vite-config-plugin-options.interface';
|
|
87
|
-
|
|
88
|
-
// ============================================================================
|
|
89
|
-
// Utilities
|
|
90
|
-
// ============================================================================
|
|
91
|
-
export { defineConfig } from './utils/define-config.util';
|
|
92
|
-
export { getNestedValue, hasNestedValue } from './utils/get-nested-value.util';
|
|
93
|
-
export { loadConfigFile } from './utils/load-config-file.util';
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Configuration Driver Interface
|
|
3
|
-
*
|
|
4
|
-
* Defines the contract for configuration drivers (env, file, firebase, etc.)
|
|
5
|
-
*/
|
|
6
|
-
export interface ConfigDriver {
|
|
7
|
-
/**
|
|
8
|
-
* Load configuration from the driver source
|
|
9
|
-
* @returns Configuration object
|
|
10
|
-
*/
|
|
11
|
-
load(): Promise<Record<string, any>> | Record<string, any>;
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Get a configuration value by key
|
|
15
|
-
* @param key - Configuration key (supports dot notation)
|
|
16
|
-
* @param defaultValue - Default value if key not found
|
|
17
|
-
*/
|
|
18
|
-
get<T = any>(key: string, defaultValue?: T): T | undefined;
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Check if a configuration key exists
|
|
22
|
-
* @param key - Configuration key
|
|
23
|
-
*/
|
|
24
|
-
has(key: string): boolean;
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Get all configuration values
|
|
28
|
-
*/
|
|
29
|
-
all(): Record<string, any>;
|
|
30
|
-
}
|
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Configuration Module Options
|
|
3
|
-
*/
|
|
4
|
-
export interface ConfigModuleOptions {
|
|
5
|
-
/**
|
|
6
|
-
* Configuration driver to use
|
|
7
|
-
* @default 'env'
|
|
8
|
-
*/
|
|
9
|
-
driver?: 'env' | 'file' | 'firebase' | string;
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Path to .env file (for env driver)
|
|
13
|
-
* @default '.env'
|
|
14
|
-
*/
|
|
15
|
-
envFilePath?: string | string[];
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Path pattern to scan for config files (for file driver)
|
|
19
|
-
* @example 'config/**\/*.config.ts'
|
|
20
|
-
*/
|
|
21
|
-
filePattern?: string | string[];
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Whether to ignore .env file
|
|
25
|
-
* @default false
|
|
26
|
-
*/
|
|
27
|
-
ignoreEnvFile?: boolean;
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Whether to expand environment variables
|
|
31
|
-
* @default false
|
|
32
|
-
*/
|
|
33
|
-
expandVariables?: boolean;
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Custom configuration object to merge
|
|
37
|
-
*/
|
|
38
|
-
load?: Record<string, any> | (() => Record<string, any> | Promise<Record<string, any>>);
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Whether configuration is global
|
|
42
|
-
* @default false
|
|
43
|
-
*/
|
|
44
|
-
isGlobal?: boolean;
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* Cache configuration values
|
|
48
|
-
* @default true
|
|
49
|
-
*/
|
|
50
|
-
cache?: boolean;
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* Validate configuration on load
|
|
54
|
-
*/
|
|
55
|
-
validate?: (config: Record<string, any>) => void | Promise<void>;
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* Firebase configuration (for firebase driver)
|
|
59
|
-
*/
|
|
60
|
-
firebase?: {
|
|
61
|
-
projectId: string;
|
|
62
|
-
configPath?: string;
|
|
63
|
-
};
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* Environment variable prefix to strip
|
|
67
|
-
* Set to 'auto' to auto-detect (VITE_ for Vite, NEXT_PUBLIC_ for Next.js)
|
|
68
|
-
* Set to 'VITE_' or 'NEXT_PUBLIC_' for specific framework
|
|
69
|
-
* Set to a custom string to strip that prefix
|
|
70
|
-
* Set to false to disable prefix stripping
|
|
71
|
-
* @default 'auto'
|
|
72
|
-
* @example 'VITE_' - strips VITE_ prefix, so VITE_APP_NAME becomes APP_NAME
|
|
73
|
-
* @example 'NEXT_PUBLIC_' - strips NEXT_PUBLIC_ prefix, so NEXT_PUBLIC_API_URL becomes API_URL
|
|
74
|
-
* @example 'auto' - auto-detects framework and strips appropriate prefix
|
|
75
|
-
*/
|
|
76
|
-
envPrefix?: 'auto' | 'VITE_' | 'NEXT_PUBLIC_' | string | false;
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* Global variable name to read config from in browser
|
|
80
|
-
* @default '__APP_CONFIG__'
|
|
81
|
-
* @example '__APP_CONFIG__' - reads from window.__APP_CONFIG__
|
|
82
|
-
*/
|
|
83
|
-
globalName?: string;
|
|
84
|
-
}
|