runtime-config-loader 6.0.0 → 6.1.0
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/README.md
CHANGED
|
@@ -6,53 +6,237 @@ Most applications require certain configuration values that can be changed at ru
|
|
|
6
6
|
|
|
7
7
|
This library provides an easy way to load one or more JSON files with configuration values or make one or more HTTP GET calls to an API endpoint that returns those values. The config objects that are returned from the call(s) will be combined into a single configuration object. You can then use that configuration throughout the application. The default location of the JSON file is in the `assets` folder, at `./assets/config.json`. When the service loads the file, it stores that configuration object in a local variable which can be accessed via the `getConfig()` and `getConfigObjectKey(key: string)` methods. `getConfig` returns the entire configuration object; `getConfigObjectKey(key: string)` returns part of the configuration object, namely the part defined by the key passed in. In some cases, the `config.json` is not finished loading before other modules/services are, so the above methods will return null. If that is the case, subscribe to the `configSubject` and access the configuration object that way.
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
### How to Implement
|
|
10
10
|
|
|
11
|
-
In your `app.
|
|
11
|
+
In your Angular application's `app.config.ts` (or wherever you provide your environment providers), use `provideRuntimeConfig`:
|
|
12
12
|
|
|
13
13
|
```ts
|
|
14
|
-
|
|
14
|
+
import { provideRuntimeConfig } from 'runtime-config-loader';
|
|
15
|
+
|
|
16
|
+
export const appConfig: ApplicationConfig = {
|
|
17
|
+
providers: [
|
|
18
|
+
// ...,
|
|
19
|
+
provideRuntimeConfig({ configUrl: './assets/config.json' }),
|
|
20
|
+
// ...
|
|
21
|
+
],
|
|
22
|
+
};
|
|
15
23
|
```
|
|
16
24
|
|
|
17
|
-
That's it; it's that simple.
|
|
25
|
+
That's it; it's that simple. The `provideRuntimeConfig` function sets up the `APP_INITIALIZER` token to load the configuration from a file or an API endpoint before the application starts.
|
|
18
26
|
|
|
19
|
-
|
|
27
|
+
### Type Safety with Generics
|
|
28
|
+
|
|
29
|
+
There are two main ways to use generics for type safety in your application.
|
|
30
|
+
|
|
31
|
+
#### Option 1: Using the `RUNTIME_CONFIG` Token (Recommended)
|
|
32
|
+
|
|
33
|
+
You can provide the type directly in `provideRuntimeConfig`. This also sets up the `RUNTIME_CONFIG` injection token, which you can use to inject the typed configuration object directly into your components or services.
|
|
34
|
+
|
|
35
|
+
```ts
|
|
36
|
+
// app.config.ts
|
|
37
|
+
provideRuntimeConfig<MyConfig>({ configUrl: './assets/config.json' })
|
|
38
|
+
|
|
39
|
+
// component.ts
|
|
40
|
+
import { RUNTIME_CONFIG } from 'runtime-config-loader';
|
|
41
|
+
|
|
42
|
+
constructor(@Inject(RUNTIME_CONFIG) private config: MyConfig) {
|
|
43
|
+
console.log(this.config.apiUrl); // Fully typed!
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
#### Option 2: Using the Service with a Type Alias
|
|
48
|
+
|
|
49
|
+
If you prefer to use the `RuntimeConfigLoaderService` methods (like `getConfigObjectKey`), you can define a type alias to avoid repeating the generic type everywhere.
|
|
50
|
+
|
|
51
|
+
```ts
|
|
52
|
+
// config.service.ts
|
|
53
|
+
export type MyConfigService = RuntimeConfigLoaderService<MyConfig>;
|
|
54
|
+
|
|
55
|
+
// component.ts
|
|
56
|
+
constructor(private configSvc: MyConfigService) {
|
|
57
|
+
const apiUrl = this.configSvc.getConfigObjectKey('apiUrl'); // Typed as string | null
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
#### Option 3: Specific Configuration Tokens
|
|
62
|
+
|
|
63
|
+
If you prefer your components to depend only on specific configuration values rather than the entire configuration object, you can use the `provideConfigToken` helper. This allows you to inject individual configuration properties cleanly and maintain strict boundaries.
|
|
64
|
+
|
|
65
|
+
```ts
|
|
66
|
+
import { InjectionToken } from '@angular/core';
|
|
67
|
+
import { provideRuntimeConfig, provideConfigToken } from 'runtime-config-loader';
|
|
68
|
+
|
|
69
|
+
// 1. Define tokens for your specific configuration values
|
|
70
|
+
export const API_URL = new InjectionToken<string>('API_URL');
|
|
71
|
+
|
|
72
|
+
// 2. Provide them using the helper
|
|
73
|
+
export const appConfig: ApplicationConfig = {
|
|
74
|
+
providers: [
|
|
75
|
+
provideRuntimeConfig<MyConfig>({ configUrl: './assets/config.json' }),
|
|
76
|
+
|
|
77
|
+
// Provide the specific token mapping it to a key in your config
|
|
78
|
+
provideConfigToken(API_URL, 'apiUrl'),
|
|
79
|
+
|
|
80
|
+
// It also supports dot-notation for nested keys
|
|
81
|
+
// provideConfigToken(NESTED_TOKEN, 'api.baseUrl')
|
|
82
|
+
],
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
// 3. Inject them directly
|
|
86
|
+
// component.ts
|
|
87
|
+
constructor(@Inject(API_URL) private apiUrl: string) {
|
|
88
|
+
console.log(this.apiUrl); // Typed as string | null
|
|
89
|
+
}
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Nested Key Access (Dot-Notation)
|
|
93
|
+
|
|
94
|
+
The `getConfigObjectKey` method supports dot-notation for accessing deeply nested configuration values.
|
|
95
|
+
|
|
96
|
+
```ts
|
|
97
|
+
// For a config like: { api: { baseUrl: 'https://api.com' } }
|
|
98
|
+
const baseUrl = this.configSvc.getConfigObjectKey('api.baseUrl'); // Returns 'https://api.com'
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
> [!NOTE]
|
|
102
|
+
> When using dot-notation for nested keys, the return type will be `any` unless you provide an explicit generic type to the call:
|
|
103
|
+
> `this.configSvc.getConfigObjectKey<string>('api.baseUrl')`
|
|
104
|
+
|
|
105
|
+
### Configuration
|
|
106
|
+
|
|
107
|
+
The `provideRuntimeConfig` function accepts a configuration object with a `configUrl` property. This can be a single string or an array of strings.
|
|
108
|
+
|
|
109
|
+
#### Single Config File
|
|
110
|
+
|
|
111
|
+
The default location is `./assets/config.json`. If you'd like to load the file from a different location:
|
|
112
|
+
|
|
113
|
+
```ts
|
|
114
|
+
provideRuntimeConfig({ configUrl: './path/to/config/config.json' });
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
#### Multiple Config Files
|
|
118
|
+
|
|
119
|
+
You can load multiple files (or API endpoints) and they will be merged into a single configuration object.
|
|
120
|
+
|
|
121
|
+
```ts
|
|
122
|
+
provideRuntimeConfig({
|
|
123
|
+
configUrl: [
|
|
124
|
+
'./path/to/config/config-1.json',
|
|
125
|
+
'./path/to/config/config-2.json',
|
|
126
|
+
],
|
|
127
|
+
});
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
If an attribute is repeated in multiple configuration files, the latest value is kept. For example, if `apiUrl` exists in both files above, the value from `config-2.json` will override the value from `config-1.json`.
|
|
131
|
+
|
|
132
|
+
#### Fallback Configuration
|
|
133
|
+
|
|
134
|
+
If you'd like the application to gracefully fall back to a default configuration in the event that the config file(s) fail to load (e.g., due to network errors or 404s), you can provide a `defaultConfig` object.
|
|
20
135
|
|
|
21
136
|
```ts
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
137
|
+
provideRuntimeConfig({
|
|
138
|
+
configUrl: './assets/config.json',
|
|
139
|
+
defaultConfig: {
|
|
140
|
+
apiUrl: 'https://fallback.api.com',
|
|
141
|
+
theme: 'light',
|
|
142
|
+
},
|
|
143
|
+
});
|
|
28
144
|
```
|
|
29
145
|
|
|
30
|
-
|
|
146
|
+
When a failure occurs and `defaultConfig` is provided, the application will emit a console warning (`Falling back to default configuration`), load the provided object, and proceed with initialization.
|
|
147
|
+
|
|
148
|
+
### HTTP Options and Headers
|
|
149
|
+
|
|
150
|
+
You can pass standard Angular `HttpClient` options (such as custom `HttpHeaders` or `HttpContext`) to the underlying HTTP request doing the fetching.
|
|
151
|
+
|
|
152
|
+
Pass an `options` object into the `provideRuntimeConfig` function:
|
|
31
153
|
|
|
32
154
|
```ts
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
155
|
+
import { HttpHeaders } from '@angular/common/http';
|
|
156
|
+
|
|
157
|
+
provideRuntimeConfig({
|
|
158
|
+
configUrl: './assets/config.json',
|
|
159
|
+
options: {
|
|
160
|
+
headers: new HttpHeaders({
|
|
161
|
+
Authorization: 'Bearer YOUR_TOKEN_HERE',
|
|
162
|
+
'X-Custom-Header': 'custom-value',
|
|
163
|
+
}),
|
|
164
|
+
withCredentials: true,
|
|
165
|
+
},
|
|
166
|
+
});
|
|
39
167
|
```
|
|
40
168
|
|
|
41
|
-
|
|
169
|
+
This is useful for APIs that require authentication or tracking headers to return configuration data.
|
|
42
170
|
|
|
43
|
-
|
|
171
|
+
### Runtime Schema Validation
|
|
44
172
|
|
|
45
|
-
|
|
173
|
+
You can provide an optional `validator` function to verify the configuration before the application starts. If validation fails (returns `false`, throws an error, or emits an error), the configuration will be set to `null`.
|
|
46
174
|
|
|
47
|
-
|
|
175
|
+
The validator supports synchronous results, `Promise<boolean>`, and `Observable<boolean>`.
|
|
48
176
|
|
|
49
177
|
```ts
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
178
|
+
provideRuntimeConfig<MyConfig>({
|
|
179
|
+
configUrl: './assets/config.json',
|
|
180
|
+
validator: (config) => {
|
|
181
|
+
return !!config.apiUrl && !!config.apiKey;
|
|
182
|
+
},
|
|
183
|
+
});
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
#### Integration with Zod
|
|
187
|
+
|
|
188
|
+
This feature integrates well with schema validation libraries like [Zod](https://zod.dev):
|
|
189
|
+
|
|
190
|
+
```ts
|
|
191
|
+
import { z } from 'zod';
|
|
192
|
+
|
|
193
|
+
const ConfigSchema = z.object({
|
|
194
|
+
apiUrl: z.string().url(),
|
|
195
|
+
apiKey: z.string().min(10),
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
provideRuntimeConfig({
|
|
199
|
+
configUrl: './assets/config.json',
|
|
200
|
+
validator: (config) => ConfigSchema.safeParse(config).success,
|
|
201
|
+
});
|
|
56
202
|
```
|
|
57
203
|
|
|
58
|
-
|
|
204
|
+
Make sure that the path(s) you provide are accessible by the Angular application. The `assets` folder is generally the easiest place to serve these files.
|
|
205
|
+
|
|
206
|
+
### Testing
|
|
207
|
+
|
|
208
|
+
When writing unit tests for components or services that depend on `RUNTIME_CONFIG` or `RuntimeConfigLoaderService`, you can easily mock the configuration using the `provideMockRuntimeConfig` utility.
|
|
209
|
+
|
|
210
|
+
This avoids making HTTP requests and allows you to instantly return a mocked configuration object of your choosing.
|
|
211
|
+
|
|
212
|
+
```ts
|
|
213
|
+
import { TestBed } from '@angular/core/testing';
|
|
214
|
+
import {
|
|
215
|
+
provideMockRuntimeConfig,
|
|
216
|
+
RUNTIME_CONFIG,
|
|
217
|
+
RuntimeConfigLoaderService,
|
|
218
|
+
} from 'runtime-config-loader';
|
|
219
|
+
|
|
220
|
+
describe('MyComponent', () => {
|
|
221
|
+
beforeEach(() => {
|
|
222
|
+
TestBed.configureTestingModule({
|
|
223
|
+
providers: [
|
|
224
|
+
// Provide the mock configuration object
|
|
225
|
+
provideMockRuntimeConfig({
|
|
226
|
+
apiUrl: 'https://mock-api.com',
|
|
227
|
+
theme: 'dark',
|
|
228
|
+
}),
|
|
229
|
+
],
|
|
230
|
+
});
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
it('should use the mocked config', () => {
|
|
234
|
+
const config = TestBed.inject(RUNTIME_CONFIG);
|
|
235
|
+
expect(config.apiUrl).toBe('https://mock-api.com');
|
|
236
|
+
|
|
237
|
+
// If testing something that uses the service directly:
|
|
238
|
+
const service = TestBed.inject(RuntimeConfigLoaderService);
|
|
239
|
+
expect(service.getConfigObjectKey('theme')).toBe('dark');
|
|
240
|
+
});
|
|
241
|
+
});
|
|
242
|
+
```
|
|
@@ -1,62 +1,102 @@
|
|
|
1
1
|
import { HttpClient, provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';
|
|
2
2
|
import * as i0 from '@angular/core';
|
|
3
|
-
import { inject, Injectable, provideAppInitializer, makeEnvironmentProviders } from '@angular/core';
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
3
|
+
import { inject, Injectable, InjectionToken, provideAppInitializer, makeEnvironmentProviders } from '@angular/core';
|
|
4
|
+
import { ReplaySubject, forkJoin, isObservable, of, from } from 'rxjs';
|
|
5
|
+
import { map, catchError, switchMap, tap, take } from 'rxjs/operators';
|
|
6
6
|
|
|
7
7
|
class RuntimeConfig {
|
|
8
8
|
constructor(obj = {}) {
|
|
9
9
|
this.configUrl = obj.configUrl || './assets/config.json';
|
|
10
|
+
this.defaultConfig = obj.defaultConfig;
|
|
11
|
+
this.validator = obj.validator;
|
|
12
|
+
this.options = obj.options;
|
|
10
13
|
}
|
|
11
14
|
}
|
|
12
15
|
|
|
13
16
|
class RuntimeConfigLoaderService {
|
|
14
17
|
constructor() {
|
|
15
18
|
this.configUrl = './assets/config.json';
|
|
16
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
17
19
|
this.configObject = null;
|
|
18
|
-
|
|
19
|
-
this.configSubject = new Subject();
|
|
20
|
+
this.configSubject = new ReplaySubject(1);
|
|
20
21
|
this._http = inject(HttpClient);
|
|
21
22
|
this._config = inject(RuntimeConfig, { optional: true });
|
|
22
23
|
if (this._config) {
|
|
23
24
|
this.configUrl = this._config.configUrl;
|
|
24
25
|
}
|
|
25
26
|
}
|
|
26
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
27
27
|
loadConfig() {
|
|
28
28
|
const urls = Array.isArray(this.configUrl)
|
|
29
29
|
? this.configUrl
|
|
30
30
|
: [this.configUrl];
|
|
31
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
32
31
|
const observables = urls.map((url) => this.makeHttpCall(url));
|
|
33
|
-
return forkJoin(observables).pipe(
|
|
34
|
-
|
|
35
|
-
tap((configDataArray) => {
|
|
36
|
-
this.configObject = configDataArray.reduce(
|
|
37
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
38
|
-
(acc, configData) => {
|
|
32
|
+
return forkJoin(observables).pipe(map((configDataArray) => {
|
|
33
|
+
const combinedConfig = configDataArray.reduce((acc, configData) => {
|
|
39
34
|
return { ...acc, ...configData };
|
|
40
35
|
}, {});
|
|
36
|
+
if (this._config && this._config.validator) {
|
|
37
|
+
const validationResult = this._config.validator(combinedConfig);
|
|
38
|
+
if (isObservable(validationResult)) {
|
|
39
|
+
return validationResult.pipe(map((isValid) => this.handleValidationResult(isValid, combinedConfig)), catchError((err) => {
|
|
40
|
+
console.error('Config validation error', err);
|
|
41
|
+
return of(this.handleValidationResult(false));
|
|
42
|
+
}));
|
|
43
|
+
}
|
|
44
|
+
else if (validationResult instanceof Promise) {
|
|
45
|
+
return from(validationResult).pipe(map((isValid) => this.handleValidationResult(isValid, combinedConfig)), catchError((err) => {
|
|
46
|
+
console.error('Config validation error', err);
|
|
47
|
+
return of(this.handleValidationResult(false));
|
|
48
|
+
}));
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
const isValid = validationResult === undefined ||
|
|
52
|
+
validationResult === true;
|
|
53
|
+
return of(this.handleValidationResult(isValid, combinedConfig));
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return of(this.handleValidationResult(true, combinedConfig));
|
|
57
|
+
}), switchMap((obs) => obs), tap((config) => {
|
|
58
|
+
this.configObject = config;
|
|
41
59
|
this.configSubject.next(this.configObject);
|
|
42
|
-
}),
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
60
|
+
}), catchError((err) => {
|
|
61
|
+
console.error('Error loading config', err);
|
|
62
|
+
if (this._config && this._config.defaultConfig !== undefined) {
|
|
63
|
+
console.warn('Falling back to default configuration');
|
|
64
|
+
this.configObject = this._config.defaultConfig;
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
this.configObject = null;
|
|
68
|
+
}
|
|
47
69
|
this.configSubject.next(this.configObject);
|
|
48
|
-
return of(
|
|
70
|
+
return of(this.configObject);
|
|
49
71
|
}));
|
|
50
72
|
}
|
|
51
|
-
|
|
73
|
+
handleValidationResult(isValid, config) {
|
|
74
|
+
if (isValid === false) {
|
|
75
|
+
console.error('Config validation failed');
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
return config || null;
|
|
79
|
+
}
|
|
52
80
|
makeHttpCall(url) {
|
|
53
|
-
return this._http.get(url).pipe(take(1));
|
|
81
|
+
return this._http.get(url, this._config?.options).pipe(take(1));
|
|
54
82
|
}
|
|
55
83
|
getConfig() {
|
|
56
84
|
return this.configObject;
|
|
57
85
|
}
|
|
58
86
|
getConfigObjectKey(key) {
|
|
59
|
-
|
|
87
|
+
if (!this.configObject) {
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
if (typeof key === 'string' && key.indexOf('.') > -1) {
|
|
91
|
+
return this.getValueByPath(this.configObject, key);
|
|
92
|
+
}
|
|
93
|
+
return this.configObject[key] ?? null;
|
|
94
|
+
}
|
|
95
|
+
getValueByPath(obj, path) {
|
|
96
|
+
const value = path.split('.').reduce((prev, curr) => {
|
|
97
|
+
return prev ? prev[curr] : null;
|
|
98
|
+
}, obj);
|
|
99
|
+
return value ?? null;
|
|
60
100
|
}
|
|
61
101
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: RuntimeConfigLoaderService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
62
102
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: RuntimeConfigLoaderService }); }
|
|
@@ -65,6 +105,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
|
|
|
65
105
|
type: Injectable
|
|
66
106
|
}], ctorParameters: () => [] });
|
|
67
107
|
|
|
108
|
+
const RUNTIME_CONFIG = new InjectionToken('RUNTIME_CONFIG');
|
|
68
109
|
function initConfig(configSvc) {
|
|
69
110
|
return () => configSvc.loadConfig();
|
|
70
111
|
}
|
|
@@ -75,6 +116,11 @@ function provideRuntimeConfig(config) {
|
|
|
75
116
|
useValue: config,
|
|
76
117
|
},
|
|
77
118
|
RuntimeConfigLoaderService,
|
|
119
|
+
{
|
|
120
|
+
provide: RUNTIME_CONFIG,
|
|
121
|
+
useFactory: (configSvc) => configSvc.getConfig(),
|
|
122
|
+
deps: [RuntimeConfigLoaderService],
|
|
123
|
+
},
|
|
78
124
|
provideAppInitializer(() => {
|
|
79
125
|
const initializerFn = initConfig(inject(RuntimeConfigLoaderService));
|
|
80
126
|
return initializerFn();
|
|
@@ -83,10 +129,75 @@ function provideRuntimeConfig(config) {
|
|
|
83
129
|
];
|
|
84
130
|
return makeEnvironmentProviders(providers);
|
|
85
131
|
}
|
|
132
|
+
function provideConfigToken(token, key) {
|
|
133
|
+
return {
|
|
134
|
+
provide: token,
|
|
135
|
+
useFactory: (configSvc) => configSvc.getConfigObjectKey(key),
|
|
136
|
+
deps: [RuntimeConfigLoaderService],
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
class MockRuntimeConfigLoaderService {
|
|
141
|
+
constructor() {
|
|
142
|
+
this.configObject = null;
|
|
143
|
+
this.configSubject = new ReplaySubject(1);
|
|
144
|
+
}
|
|
145
|
+
loadConfig() {
|
|
146
|
+
this.configSubject.next(this.configObject);
|
|
147
|
+
return of(this.configObject);
|
|
148
|
+
}
|
|
149
|
+
getConfig() {
|
|
150
|
+
return this.configObject;
|
|
151
|
+
}
|
|
152
|
+
getConfigObjectKey(key) {
|
|
153
|
+
if (!this.configObject) {
|
|
154
|
+
return null;
|
|
155
|
+
}
|
|
156
|
+
if (typeof key === 'string' && key.indexOf('.') > -1) {
|
|
157
|
+
return this.getValueByPath(this.configObject, key);
|
|
158
|
+
}
|
|
159
|
+
return this.configObject[key] ?? null;
|
|
160
|
+
}
|
|
161
|
+
getValueByPath(obj, path) {
|
|
162
|
+
const value = path.split('.').reduce((prev, curr) => {
|
|
163
|
+
return prev ? prev[curr] : null;
|
|
164
|
+
}, obj);
|
|
165
|
+
return value ?? null;
|
|
166
|
+
}
|
|
167
|
+
setMockConfig(config) {
|
|
168
|
+
this.configObject = config;
|
|
169
|
+
this.configSubject.next(this.configObject);
|
|
170
|
+
}
|
|
171
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: MockRuntimeConfigLoaderService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
172
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: MockRuntimeConfigLoaderService }); }
|
|
173
|
+
}
|
|
174
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: MockRuntimeConfigLoaderService, decorators: [{
|
|
175
|
+
type: Injectable
|
|
176
|
+
}] });
|
|
177
|
+
|
|
178
|
+
function provideMockRuntimeConfig(mockConfig) {
|
|
179
|
+
const mockService = new MockRuntimeConfigLoaderService();
|
|
180
|
+
mockService.setMockConfig(mockConfig);
|
|
181
|
+
const providers = [
|
|
182
|
+
{
|
|
183
|
+
provide: RuntimeConfigLoaderService,
|
|
184
|
+
useValue: mockService,
|
|
185
|
+
},
|
|
186
|
+
{
|
|
187
|
+
provide: MockRuntimeConfigLoaderService,
|
|
188
|
+
useValue: mockService,
|
|
189
|
+
},
|
|
190
|
+
{
|
|
191
|
+
provide: RUNTIME_CONFIG,
|
|
192
|
+
useValue: mockConfig,
|
|
193
|
+
},
|
|
194
|
+
];
|
|
195
|
+
return makeEnvironmentProviders(providers);
|
|
196
|
+
}
|
|
86
197
|
|
|
87
198
|
/**
|
|
88
199
|
* Generated bundle index. Do not edit.
|
|
89
200
|
*/
|
|
90
201
|
|
|
91
|
-
export { RuntimeConfig, RuntimeConfigLoaderService, initConfig, provideRuntimeConfig };
|
|
202
|
+
export { MockRuntimeConfigLoaderService, RUNTIME_CONFIG, RuntimeConfig, RuntimeConfigLoaderService, initConfig, provideConfigToken, provideMockRuntimeConfig, provideRuntimeConfig };
|
|
92
203
|
//# sourceMappingURL=runtime-config-loader.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime-config-loader.mjs","sources":["../../../../libs/runtime-config-loader/src/lib/runtime-config.ts","../../../../libs/runtime-config-loader/src/lib/runtime-config-loader/runtime-config-loader.service.ts","../../../../libs/runtime-config-loader/src/lib/runtime-config-loader.provider.ts","../../../../libs/runtime-config-loader/src/runtime-config-loader.ts"],"sourcesContent":["export class RuntimeConfig {\n\tconfigUrl: string | string[];\n\n\tconstructor(obj: { configUrl?: string | string[] } = {}) {\n\t\tthis.configUrl = obj.configUrl || './assets/config.json';\n\t}\n}\n","import { HttpClient } from '@angular/common/http';\nimport { Injectable, inject } from '@angular/core';\nimport { RuntimeConfig } from '../runtime-config';\nimport { forkJoin, Observable, of, Subject } from 'rxjs';\nimport { catchError, take, tap } from 'rxjs/operators';\n\n@Injectable()\nexport class RuntimeConfigLoaderService {\n\tprivate configUrl: string | string[] = './assets/config.json';\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\tprivate configObject: any = null;\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\tpublic configSubject: Subject<any> = new Subject<any>();\n\n\tprivate _http = inject(HttpClient);\n\tprivate _config = inject(RuntimeConfig, { optional: true });\n\n\tconstructor() {\n\t\tif (this._config) {\n\t\t\tthis.configUrl = this._config.configUrl;\n\t\t}\n\t}\n\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\tloadConfig(): Observable<any> {\n\t\tconst urls: string[] = Array.isArray(this.configUrl)\n\t\t\t? this.configUrl\n\t\t\t: [this.configUrl];\n\n\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\t\tconst observables: Observable<any>[] = urls.map((url) =>\n\t\t\tthis.makeHttpCall(url)\n\t\t);\n\n\t\treturn forkJoin(observables).pipe(\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\t\t\ttap((configDataArray: any[]) => {\n\t\t\t\tthis.configObject = configDataArray.reduce(\n\t\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\t\t\t\t\t(acc, configData) => {\n\t\t\t\t\t\treturn { ...acc, ...configData };\n\t\t\t\t\t},\n\t\t\t\t\t{}\n\t\t\t\t);\n\n\t\t\t\tthis.configSubject.next(this.configObject);\n\t\t\t}),\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\t\t\tcatchError((err: any) => {\n\t\t\t\tconsole.error('Error loading config: ', err);\n\t\t\t\tthis.configObject = null;\n\t\t\t\tthis.configSubject.next(this.configObject);\n\t\t\t\treturn of(null);\n\t\t\t})\n\t\t);\n\t}\n\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\tprivate makeHttpCall(url: string): Observable<any> {\n\t\treturn this._http.get(url).pipe(take(1));\n\t}\n\n\tgetConfig() {\n\t\treturn this.configObject;\n\t}\n\n\tgetConfigObjectKey(key: string) {\n\t\treturn this.configObject ? this.configObject[key] : null;\n\t}\n}\n","import {\n\tEnvironmentProviders,\n\tProvider,\n\tinject,\n\tmakeEnvironmentProviders,\n\tprovideAppInitializer,\n} from '@angular/core';\nimport {\n\tprovideHttpClient,\n\twithInterceptorsFromDi,\n} from '@angular/common/http';\nimport { RuntimeConfig } from './runtime-config';\nimport { RuntimeConfigLoaderService } from './runtime-config-loader/runtime-config-loader.service';\n\nexport function initConfig(configSvc: RuntimeConfigLoaderService) {\n\treturn () => configSvc.loadConfig();\n}\n\nexport function provideRuntimeConfig(\n\tconfig: RuntimeConfig\n): EnvironmentProviders {\n\tconst providers: (Provider | EnvironmentProviders)[] = [\n\t\t{\n\t\t\tprovide: RuntimeConfig,\n\t\t\tuseValue: config,\n\t\t},\n\t\tRuntimeConfigLoaderService,\n\t\tprovideAppInitializer(() => {\n\t\t\tconst initializerFn = initConfig(\n\t\t\t\tinject(RuntimeConfigLoaderService)\n\t\t\t);\n\t\t\treturn initializerFn();\n\t\t}),\n\t\tprovideHttpClient(withInterceptorsFromDi()),\n\t];\n\n\treturn makeEnvironmentProviders(providers);\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"runtime-config-loader.mjs","sources":["../../../../libs/runtime-config-loader/src/lib/runtime-config.ts","../../../../libs/runtime-config-loader/src/lib/runtime-config-loader/runtime-config-loader.service.ts","../../../../libs/runtime-config-loader/src/lib/runtime-config-loader.provider.ts","../../../../libs/runtime-config-loader/src/lib/testing/mock-runtime-config-loader.service.ts","../../../../libs/runtime-config-loader/src/lib/testing/provide-mock-runtime-config.ts","../../../../libs/runtime-config-loader/src/runtime-config-loader.ts"],"sourcesContent":["import { Observable } from 'rxjs';\nimport { HttpContext, HttpHeaders, HttpParams } from '@angular/common/http';\n\nexport class RuntimeConfig<T = any> {\n\tconfigUrl: string | string[];\n\tdefaultConfig?: T;\n\tvalidator?: (\n\t\tconfig: T\n\t) => boolean | Promise<boolean> | Observable<boolean> | void;\n\toptions?: {\n\t\theaders?: HttpHeaders | { [header: string]: string | string[] };\n\t\tcontext?: HttpContext;\n\t\tobserve?: 'body';\n\t\tparams?:\n\t\t\t| HttpParams\n\t\t\t| {\n\t\t\t\t\t[param: string]:\n\t\t\t\t\t\t| string\n\t\t\t\t\t\t| number\n\t\t\t\t\t\t| boolean\n\t\t\t\t\t\t| ReadonlyArray<string | number | boolean>;\n\t\t\t };\n\t\treportProgress?: boolean;\n\t\tresponseType?: 'json';\n\t\twithCredentials?: boolean;\n\t};\n\n\tconstructor(\n\t\tobj: {\n\t\t\tconfigUrl?: string | string[];\n\t\t\tdefaultConfig?: T;\n\t\t\tvalidator?: (\n\t\t\t\tconfig: T\n\t\t\t) => boolean | Promise<boolean> | Observable<boolean> | void;\n\t\t\toptions?: {\n\t\t\t\theaders?: HttpHeaders | { [header: string]: string | string[] };\n\t\t\t\tcontext?: HttpContext;\n\t\t\t\tobserve?: 'body';\n\t\t\t\tparams?:\n\t\t\t\t\t| HttpParams\n\t\t\t\t\t| {\n\t\t\t\t\t\t\t[param: string]:\n\t\t\t\t\t\t\t\t| string\n\t\t\t\t\t\t\t\t| number\n\t\t\t\t\t\t\t\t| boolean\n\t\t\t\t\t\t\t\t| ReadonlyArray<string | number | boolean>;\n\t\t\t\t\t };\n\t\t\t\treportProgress?: boolean;\n\t\t\t\tresponseType?: 'json';\n\t\t\t\twithCredentials?: boolean;\n\t\t\t};\n\t\t} = {}\n\t) {\n\t\tthis.configUrl = obj.configUrl || './assets/config.json';\n\t\tthis.defaultConfig = obj.defaultConfig;\n\t\tthis.validator = obj.validator;\n\t\tthis.options = obj.options;\n\t}\n}\n","import { HttpClient } from '@angular/common/http';\nimport { Injectable, inject } from '@angular/core';\nimport { RuntimeConfig } from '../runtime-config';\nimport {\n\tforkJoin,\n\tfrom,\n\tisObservable,\n\tObservable,\n\tof,\n\tReplaySubject,\n\tSubject,\n} from 'rxjs';\nimport { catchError, map, take, tap, switchMap } from 'rxjs/operators';\n\n@Injectable()\nexport class RuntimeConfigLoaderService<T = any> {\n\tprivate configUrl: string | string[] = './assets/config.json';\n\tprivate configObject: T | null = null;\n\tpublic configSubject: Subject<T | null> = new ReplaySubject<T | null>(1);\n\n\tprivate _http = inject(HttpClient);\n\tprivate _config = inject(RuntimeConfig, { optional: true });\n\n\tconstructor() {\n\t\tif (this._config) {\n\t\t\tthis.configUrl = this._config.configUrl;\n\t\t}\n\t}\n\n\tloadConfig(): Observable<T | null> {\n\t\tconst urls: string[] = Array.isArray(this.configUrl)\n\t\t\t? this.configUrl\n\t\t\t: [this.configUrl];\n\n\t\tconst observables: Observable<any>[] = urls.map((url) =>\n\t\t\tthis.makeHttpCall(url)\n\t\t);\n\n\t\treturn forkJoin(observables).pipe(\n\t\t\tmap((configDataArray: any[]) => {\n\t\t\t\tconst combinedConfig = configDataArray.reduce(\n\t\t\t\t\t(acc, configData) => {\n\t\t\t\t\t\treturn { ...acc, ...configData };\n\t\t\t\t\t},\n\t\t\t\t\t{} as T\n\t\t\t\t);\n\n\t\t\t\tif (this._config && this._config.validator) {\n\t\t\t\t\tconst validationResult =\n\t\t\t\t\t\tthis._config.validator(combinedConfig);\n\n\t\t\t\t\tif (isObservable(validationResult)) {\n\t\t\t\t\t\treturn validationResult.pipe(\n\t\t\t\t\t\t\tmap((isValid) =>\n\t\t\t\t\t\t\t\tthis.handleValidationResult(\n\t\t\t\t\t\t\t\t\tisValid,\n\t\t\t\t\t\t\t\t\tcombinedConfig\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\tcatchError((err) => {\n\t\t\t\t\t\t\t\tconsole.error('Config validation error', err);\n\t\t\t\t\t\t\t\treturn of(this.handleValidationResult(false));\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t);\n\t\t\t\t\t} else if (validationResult instanceof Promise) {\n\t\t\t\t\t\treturn from(validationResult).pipe(\n\t\t\t\t\t\t\tmap((isValid) =>\n\t\t\t\t\t\t\t\tthis.handleValidationResult(\n\t\t\t\t\t\t\t\t\tisValid,\n\t\t\t\t\t\t\t\t\tcombinedConfig\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\tcatchError((err) => {\n\t\t\t\t\t\t\t\tconsole.error('Config validation error', err);\n\t\t\t\t\t\t\t\treturn of(this.handleValidationResult(false));\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tconst isValid =\n\t\t\t\t\t\t\tvalidationResult === undefined ||\n\t\t\t\t\t\t\tvalidationResult === true;\n\t\t\t\t\t\treturn of(\n\t\t\t\t\t\t\tthis.handleValidationResult(isValid, combinedConfig)\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn of(this.handleValidationResult(true, combinedConfig));\n\t\t\t}),\n\t\t\tswitchMap((obs) => obs),\n\t\t\ttap((config) => {\n\t\t\t\tthis.configObject = config;\n\t\t\t\tthis.configSubject.next(this.configObject);\n\t\t\t}),\n\t\t\tcatchError((err) => {\n\t\t\t\tconsole.error('Error loading config', err);\n\n\t\t\t\tif (this._config && this._config.defaultConfig !== undefined) {\n\t\t\t\t\tconsole.warn('Falling back to default configuration');\n\t\t\t\t\tthis.configObject = this._config.defaultConfig;\n\t\t\t\t} else {\n\t\t\t\t\tthis.configObject = null;\n\t\t\t\t}\n\n\t\t\t\tthis.configSubject.next(this.configObject);\n\t\t\t\treturn of(this.configObject);\n\t\t\t})\n\t\t) as Observable<T | null>;\n\t}\n\n\tprivate handleValidationResult(\n\t\tisValid: boolean | void,\n\t\tconfig?: T\n\t): T | null {\n\t\tif (isValid === false) {\n\t\t\tconsole.error('Config validation failed');\n\t\t\treturn null;\n\t\t}\n\t\treturn config || null;\n\t}\n\n\tprivate makeHttpCall(url: string): Observable<any> {\n\t\treturn this._http.get(url, this._config?.options).pipe(take(1));\n\t}\n\n\tgetConfig(): T | null {\n\t\treturn this.configObject;\n\t}\n\n\tgetConfigObjectKey<K extends keyof T>(key: K): T[K] | null;\n\tgetConfigObjectKey<R = any>(key: string): R | null;\n\tgetConfigObjectKey(key: any): any {\n\t\tif (!this.configObject) {\n\t\t\treturn null;\n\t\t}\n\n\t\tif (typeof key === 'string' && key.indexOf('.') > -1) {\n\t\t\treturn this.getValueByPath(this.configObject, key);\n\t\t}\n\n\t\treturn (this.configObject as any)[key] ?? null;\n\t}\n\n\tprivate getValueByPath(obj: any, path: string): any {\n\t\tconst value = path.split('.').reduce((prev, curr) => {\n\t\t\treturn prev ? prev[curr] : null;\n\t\t}, obj);\n\t\treturn value ?? null;\n\t}\n}\n","import {\n\tEnvironmentProviders,\n\tInjectionToken,\n\tProvider,\n\tinject,\n\tmakeEnvironmentProviders,\n\tprovideAppInitializer,\n} from '@angular/core';\nimport {\n\tprovideHttpClient,\n\twithInterceptorsFromDi,\n} from '@angular/common/http';\nimport { RuntimeConfig } from './runtime-config';\nimport { RuntimeConfigLoaderService } from './runtime-config-loader/runtime-config-loader.service';\n\nexport const RUNTIME_CONFIG = new InjectionToken<any>('RUNTIME_CONFIG');\n\nexport function initConfig(configSvc: RuntimeConfigLoaderService) {\n\treturn () => configSvc.loadConfig();\n}\n\nexport function provideRuntimeConfig<T = any>(\n\tconfig: RuntimeConfig<T>\n): EnvironmentProviders {\n\tconst providers: (Provider | EnvironmentProviders)[] = [\n\t\t{\n\t\t\tprovide: RuntimeConfig,\n\t\t\tuseValue: config,\n\t\t},\n\t\tRuntimeConfigLoaderService,\n\t\t{\n\t\t\tprovide: RUNTIME_CONFIG,\n\t\t\tuseFactory: (configSvc: RuntimeConfigLoaderService<T>) =>\n\t\t\t\tconfigSvc.getConfig(),\n\t\t\tdeps: [RuntimeConfigLoaderService],\n\t\t},\n\t\tprovideAppInitializer(() => {\n\t\t\tconst initializerFn = initConfig(\n\t\t\t\tinject(RuntimeConfigLoaderService)\n\t\t\t);\n\t\t\treturn initializerFn();\n\t\t}),\n\t\tprovideHttpClient(withInterceptorsFromDi()),\n\t];\n\n\treturn makeEnvironmentProviders(providers);\n}\n\nexport function provideConfigToken<T, K extends keyof T>(\n\ttoken: InjectionToken<T[K]>,\n\tkey: K\n): Provider;\nexport function provideConfigToken<R = any>(\n\ttoken: InjectionToken<R>,\n\tpath: string\n): Provider;\nexport function provideConfigToken(\n\ttoken: InjectionToken<any>,\n\tkey: any\n): Provider {\n\treturn {\n\t\tprovide: token,\n\t\tuseFactory: (configSvc: RuntimeConfigLoaderService) =>\n\t\t\tconfigSvc.getConfigObjectKey(key),\n\t\tdeps: [RuntimeConfigLoaderService],\n\t};\n}\n","import { Injectable } from '@angular/core';\nimport { Observable, of, Subject, ReplaySubject } from 'rxjs';\nimport { RuntimeConfigLoaderService } from '../runtime-config-loader/runtime-config-loader.service';\n\n@Injectable()\nexport class MockRuntimeConfigLoaderService<T = any>\n\timplements Partial<RuntimeConfigLoaderService<T>>\n{\n\tprivate configObject: T | null = null;\n\tpublic configSubject: Subject<T | null> = new ReplaySubject<T | null>(1);\n\n\tloadConfig(): Observable<T | null> {\n\t\tthis.configSubject.next(this.configObject);\n\t\treturn of(this.configObject);\n\t}\n\n\tgetConfig(): T | null {\n\t\treturn this.configObject;\n\t}\n\n\tgetConfigObjectKey<K extends keyof T>(key: K): T[K] | null;\n\tgetConfigObjectKey<R = any>(key: string): R | null;\n\tgetConfigObjectKey(key: any): any {\n\t\tif (!this.configObject) {\n\t\t\treturn null;\n\t\t}\n\n\t\tif (typeof key === 'string' && key.indexOf('.') > -1) {\n\t\t\treturn this.getValueByPath(this.configObject, key);\n\t\t}\n\n\t\treturn (this.configObject as any)[key] ?? null;\n\t}\n\n\tprivate getValueByPath(obj: any, path: string): any {\n\t\tconst value = path.split('.').reduce((prev, curr) => {\n\t\t\treturn prev ? prev[curr] : null;\n\t\t}, obj);\n\t\treturn value ?? null;\n\t}\n\n\tsetMockConfig(config: T): void {\n\t\tthis.configObject = config;\n\t\tthis.configSubject.next(this.configObject);\n\t}\n}\n","import {\n\tEnvironmentProviders,\n\tProvider,\n\tmakeEnvironmentProviders,\n} from '@angular/core';\nimport { RUNTIME_CONFIG } from '../runtime-config-loader.provider';\nimport { RuntimeConfigLoaderService } from '../runtime-config-loader/runtime-config-loader.service';\nimport { MockRuntimeConfigLoaderService } from './mock-runtime-config-loader.service';\n\nexport function provideMockRuntimeConfig<T = any>(\n\tmockConfig: T\n): EnvironmentProviders {\n\tconst mockService = new MockRuntimeConfigLoaderService<T>();\n\tmockService.setMockConfig(mockConfig);\n\n\tconst providers: Provider[] = [\n\t\t{\n\t\t\tprovide: RuntimeConfigLoaderService,\n\t\t\tuseValue: mockService,\n\t\t},\n\t\t{\n\t\t\tprovide: MockRuntimeConfigLoaderService,\n\t\t\tuseValue: mockService,\n\t\t},\n\t\t{\n\t\t\tprovide: RUNTIME_CONFIG,\n\t\t\tuseValue: mockConfig,\n\t\t},\n\t];\n\n\treturn makeEnvironmentProviders(providers);\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
Binary file
|
|
@@ -1,31 +1,83 @@
|
|
|
1
1
|
import * as rxjs from 'rxjs';
|
|
2
|
-
import {
|
|
2
|
+
import { Observable, Subject } from 'rxjs';
|
|
3
|
+
import { HttpHeaders, HttpContext, HttpParams } from '@angular/common/http';
|
|
3
4
|
import * as i0 from '@angular/core';
|
|
4
|
-
import { EnvironmentProviders } from '@angular/core';
|
|
5
|
+
import { InjectionToken, Provider, EnvironmentProviders } from '@angular/core';
|
|
5
6
|
|
|
6
|
-
declare class RuntimeConfig {
|
|
7
|
+
declare class RuntimeConfig<T = any> {
|
|
7
8
|
configUrl: string | string[];
|
|
9
|
+
defaultConfig?: T;
|
|
10
|
+
validator?: (config: T) => boolean | Promise<boolean> | Observable<boolean> | void;
|
|
11
|
+
options?: {
|
|
12
|
+
headers?: HttpHeaders | {
|
|
13
|
+
[header: string]: string | string[];
|
|
14
|
+
};
|
|
15
|
+
context?: HttpContext;
|
|
16
|
+
observe?: 'body';
|
|
17
|
+
params?: HttpParams | {
|
|
18
|
+
[param: string]: string | number | boolean | ReadonlyArray<string | number | boolean>;
|
|
19
|
+
};
|
|
20
|
+
reportProgress?: boolean;
|
|
21
|
+
responseType?: 'json';
|
|
22
|
+
withCredentials?: boolean;
|
|
23
|
+
};
|
|
8
24
|
constructor(obj?: {
|
|
9
25
|
configUrl?: string | string[];
|
|
26
|
+
defaultConfig?: T;
|
|
27
|
+
validator?: (config: T) => boolean | Promise<boolean> | Observable<boolean> | void;
|
|
28
|
+
options?: {
|
|
29
|
+
headers?: HttpHeaders | {
|
|
30
|
+
[header: string]: string | string[];
|
|
31
|
+
};
|
|
32
|
+
context?: HttpContext;
|
|
33
|
+
observe?: 'body';
|
|
34
|
+
params?: HttpParams | {
|
|
35
|
+
[param: string]: string | number | boolean | ReadonlyArray<string | number | boolean>;
|
|
36
|
+
};
|
|
37
|
+
reportProgress?: boolean;
|
|
38
|
+
responseType?: 'json';
|
|
39
|
+
withCredentials?: boolean;
|
|
40
|
+
};
|
|
10
41
|
});
|
|
11
42
|
}
|
|
12
43
|
|
|
13
|
-
declare class RuntimeConfigLoaderService {
|
|
44
|
+
declare class RuntimeConfigLoaderService<T = any> {
|
|
14
45
|
private configUrl;
|
|
15
46
|
private configObject;
|
|
16
|
-
configSubject: Subject<
|
|
47
|
+
configSubject: Subject<T | null>;
|
|
17
48
|
private _http;
|
|
18
49
|
private _config;
|
|
19
50
|
constructor();
|
|
20
|
-
loadConfig(): Observable<
|
|
51
|
+
loadConfig(): Observable<T | null>;
|
|
52
|
+
private handleValidationResult;
|
|
21
53
|
private makeHttpCall;
|
|
22
|
-
getConfig():
|
|
23
|
-
getConfigObjectKey(key:
|
|
24
|
-
|
|
25
|
-
|
|
54
|
+
getConfig(): T | null;
|
|
55
|
+
getConfigObjectKey<K extends keyof T>(key: K): T[K] | null;
|
|
56
|
+
getConfigObjectKey<R = any>(key: string): R | null;
|
|
57
|
+
private getValueByPath;
|
|
58
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<RuntimeConfigLoaderService<any>, never>;
|
|
59
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<RuntimeConfigLoaderService<any>>;
|
|
26
60
|
}
|
|
27
61
|
|
|
62
|
+
declare const RUNTIME_CONFIG: InjectionToken<any>;
|
|
28
63
|
declare function initConfig(configSvc: RuntimeConfigLoaderService): () => rxjs.Observable<any>;
|
|
29
|
-
declare function provideRuntimeConfig(config: RuntimeConfig): EnvironmentProviders;
|
|
64
|
+
declare function provideRuntimeConfig<T = any>(config: RuntimeConfig<T>): EnvironmentProviders;
|
|
65
|
+
declare function provideConfigToken<T, K extends keyof T>(token: InjectionToken<T[K]>, key: K): Provider;
|
|
66
|
+
declare function provideConfigToken<R = any>(token: InjectionToken<R>, path: string): Provider;
|
|
30
67
|
|
|
31
|
-
|
|
68
|
+
declare class MockRuntimeConfigLoaderService<T = any> implements Partial<RuntimeConfigLoaderService<T>> {
|
|
69
|
+
private configObject;
|
|
70
|
+
configSubject: Subject<T | null>;
|
|
71
|
+
loadConfig(): Observable<T | null>;
|
|
72
|
+
getConfig(): T | null;
|
|
73
|
+
getConfigObjectKey<K extends keyof T>(key: K): T[K] | null;
|
|
74
|
+
getConfigObjectKey<R = any>(key: string): R | null;
|
|
75
|
+
private getValueByPath;
|
|
76
|
+
setMockConfig(config: T): void;
|
|
77
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<MockRuntimeConfigLoaderService<any>, never>;
|
|
78
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<MockRuntimeConfigLoaderService<any>>;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
declare function provideMockRuntimeConfig<T = any>(mockConfig: T): EnvironmentProviders;
|
|
82
|
+
|
|
83
|
+
export { MockRuntimeConfigLoaderService, RUNTIME_CONFIG, RuntimeConfig, RuntimeConfigLoaderService, initConfig, provideConfigToken, provideMockRuntimeConfig, provideRuntimeConfig };
|
|
Binary file
|