Skip to content

Commit eac2bd0

Browse files
committed
Add 'deepEnv' decorator and use it
1 parent 50dae80 commit eac2bd0

4 files changed

Lines changed: 69 additions & 6 deletions

File tree

src/app/core/reload/reload.guard.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import { Router } from '@angular/router';
22
import { AppConfig } from '@dspace/config/app.config';
3+
import { Config } from '@dspace/config/config';
34
import { DefaultAppConfig } from '@dspace/config/default-app.config';
45

56
import { reloadGuard } from './reload.guard';
6-
import { Config } from '@dspace/config/config';
77

88
describe('reloadGuard', () => {
99
let guard: any;

src/config/cache.config.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,17 @@ export class CacheConfig extends Config {
99
// Cache-Control HTTP Header
1010
@Config.publish() control: string;
1111
@Config.publish() autoSync: AutoSyncConfig;
12+
1213
// In-memory caches of server-side rendered (SSR) content. These caches can be used to limit the frequency
1314
// of re-generating SSR pages to improve performance.
15+
@Config.deepEnv({
16+
botCache: {
17+
max: ['DSPACE_CACHE_SERVERSIDE_BOTCACHE_MAX', Number],
18+
},
19+
anonymousCache: {
20+
max: ['DSPACE_CACHE_SERVERSIDE_ANONYMOUSCACHE_MAX', Number],
21+
},
22+
})
1423
serverSide: {
1524
// Debug server-side caching. Set to true to see cache hits/misses/refreshes in console logs.
1625
debug: boolean,

src/config/config.ts

Lines changed: 53 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@ const publicMetadataKey = Symbol('public');
77
const envMetadataKey = Symbol('env');
88
const arrayMetadataKey = Symbol('arrayType');
99

10+
type DSpaceEnvVar = `DSPACE_${string}`;
11+
12+
interface DeepEnvSpec {
13+
[k: string]: DeepEnvSpec | DSpaceEnvVar | [DSpaceEnvVar, (val: string) => any];
14+
}
15+
1016
export class Config {
1117
/**
1218
* Decorator that marks a config property as public
@@ -31,10 +37,28 @@ export class Config {
3137
* value of the environment variable and returns the appropriate
3238
* type to use for the config property.
3339
*/
34-
static env(name: `DSPACE_${string}`, loader?: (val: string) => any) {
40+
static env(name: DSpaceEnvVar, loader?: (val: string) => any) {
3541
return Reflect.metadata(envMetadataKey, { name, loader });
3642
}
3743

44+
45+
/**
46+
* Decorator for changing a deeply nested config property via an environment variable
47+
*
48+
* The method 'Config#applyEnv' will load object properties with
49+
* this decoration from the environment object passed in.
50+
*
51+
* @param spec A plain object whose structure at least partially
52+
* matches that of the property being decorated, with values being
53+
* either a string environment variable name for that nested
54+
* property, or an array of a string environment variable name and
55+
* loader function which can transform the environment variable
56+
* value into the desired type.
57+
*/
58+
static deepEnv(spec: DeepEnvSpec) {
59+
return Reflect.metadata(envMetadataKey, { deep: true, spec });
60+
}
61+
3862
/**
3963
* Decorator to mark a config property as an array of another type of Config
4064
*
@@ -152,6 +176,27 @@ export class Config {
152176
// be a map of environment variable names to their values, such as
153177
// in `process.env`.
154178
protected applyEnvironment(env: { [k: string]: string }) {
179+
const deepEnv = (
180+
target: any, spec: any, envObj: { [k: string]: string },
181+
) => {
182+
Object.keys(spec).forEach(k => {
183+
if (typeof spec[k] === 'string') {
184+
const val = envObj[spec[k]];
185+
if (isNotEmpty(val)) {
186+
target[k] = val;
187+
}
188+
} else if (Array.isArray(spec[k])
189+
&& (typeof spec[k][0] === 'string')) {
190+
const val = envObj[spec[k][0]];
191+
if (isNotEmpty(val)) {
192+
target[k] = spec[k][1](val);
193+
}
194+
} else {
195+
deepEnv(target[k], spec[k], envObj);
196+
}
197+
});
198+
};
199+
155200
Object.keys(this).forEach(k => {
156201
if (this[k] instanceof Config) {
157202
this[k].applyEnvironment(env);
@@ -160,9 +205,13 @@ export class Config {
160205
} else {
161206
const envMeta = Reflect.getMetadata(envMetadataKey, this, k);
162207
if (envMeta) {
163-
const val = env[envMeta.name];
164-
if (isNotEmpty(val)) {
165-
this[k] = envMeta.loader ? envMeta.loader(val) : val;
208+
if (envMeta.deep) {
209+
deepEnv(this[k], envMeta.spec, env);
210+
} else {
211+
const val = env[envMeta.name];
212+
if (isNotEmpty(val)) {
213+
this[k] = envMeta.loader ? envMeta.loader(val) : val;
214+
}
166215
}
167216
}
168217
}

src/config/info.config.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
11
import { Config } from './config';
22

3+
const toBoolean = (val: string) => (val === 'true' || val === '1');
4+
35
export class InfoConfig extends Config {
46
@Config.publish() enableEndUserAgreement?: boolean;
57
@Config.publish() enablePrivacyStatement?: boolean;
68
@Config.publish() enableCOARNotifySupport?: boolean;
7-
@Config.publish() enableCookieConsentPopup?: boolean;
9+
10+
@Config.publish()
11+
@Config.env('DSPACE_INFO_ENABLECOOKIECONSENTPOPUP', toBoolean)
12+
enableCookieConsentPopup?: boolean;
813
}

0 commit comments

Comments
 (0)