-
Notifications
You must be signed in to change notification settings - Fork 210
Expand file tree
/
Copy pathconfig.service.ts
More file actions
86 lines (81 loc) · 3.41 KB
/
config.service.ts
File metadata and controls
86 lines (81 loc) · 3.41 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
import { Inject, Injectable, Optional } from '@angular/core';
import { Observable, Subject } from 'rxjs';
import { filter, mapTo } from 'rxjs/operators';
import { DevUIGlobalConfig, DevUIGlobalConfigKey, DevUIGlobalConfigToken, DevUIGlobalInsideConfigKey } from './config';
const isDefined = function (value?: any): boolean {
return value !== undefined;
};
@Injectable({
providedIn: 'root',
})
export class DevConfigService {
private configUpdated$ = new Subject<keyof DevUIGlobalConfig>();
private config: DevUIGlobalConfig;
constructor(@Optional() @Inject(DevUIGlobalConfigToken) defaultConfig?: DevUIGlobalConfig) {
this.config = defaultConfig || {};
}
getConfigForComponent<T extends DevUIGlobalConfigKey>(componentName: T): DevUIGlobalConfig[T] {
return this.config[componentName];
}
getConfigForApi<T extends DevUIGlobalInsideConfigKey>(api: T): DevUIGlobalConfig['global'][T] {
const globalConfig = this.config['global'] || {};
const apiConfig = globalConfig[api];
return apiConfig;
}
getConfigChangeEventForComponent(componentName: DevUIGlobalConfigKey): Observable<void> {
return this.configUpdated$.pipe(
filter((n) => n === componentName),
mapTo(undefined)
);
}
set<T extends DevUIGlobalConfigKey>(componentName: T, value: DevUIGlobalConfig[T]): void {
this.config[componentName] = { ...this.config[componentName], ...value };
this.configUpdated$.next(componentName);
}
}
export function WithConfig<T>(propertyKey?: T | string) {
return function ConfigDecorator(target: any, propName: any, originalDescriptor?: TypedPropertyDescriptor<T>): any {
const privatePropName = `$$__assignedValue__${propName}`;
if (Object.prototype.hasOwnProperty.call(target, privatePropName)) {
console.warn(`The prop "${privatePropName}" is already exist, it will be overrided by withConfig decorator.`);
}
Object.defineProperty(target, privatePropName, {
configurable: true,
writable: true,
enumerable: false,
});
return {
get(): T | undefined {
const originalValue = originalDescriptor?.get ? originalDescriptor.get.bind(this)() : this[privatePropName];
const assignedByUser = ((this.assignmentCount || {})[propName] || 0) > 1;
if (assignedByUser && isDefined(originalValue)) {
return originalValue;
}
if (JSON.stringify(this.devConfigService.config) === '{}') {
return originalValue;
}
let name = this.constructor.name;
name = name.replace('Directive', '');
name = name.replace('Component', '');
name = name.replace('Pipe', '');
name = name.toLowerCase();
const componentConfig = this.devConfigService.config[name] || {};
const configValue = componentConfig[propName];
const globalConfig = this.devConfigService.config['global'] || {};
const apiConfig = globalConfig[propName];
const ret = isDefined(configValue) ? configValue : isDefined(apiConfig) ? apiConfig : originalValue;
return ret;
},
set(value?: T): void {
this.assignmentCount = this.assignmentCount || {};
this.assignmentCount[propName] = (this.assignmentCount[propName] || 0) + 1;
if (originalDescriptor && originalDescriptor.set) {
originalDescriptor.set.bind(this)(value);
}
this[privatePropName] = value;
},
configurable: true,
enumerable: true,
};
};
}