-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.ts
More file actions
171 lines (146 loc) · 4.89 KB
/
Copy pathindex.ts
File metadata and controls
171 lines (146 loc) · 4.89 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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
/* eslint-disable @typescript-eslint/no-unsafe-type-assertion */
type PropertyValue<V> =
| {
propertyFound: false
}
| {
propertyFound: true
propertyValue: V
}
export class Configurator<D extends Record<string, unknown>> {
readonly #defaultValues: D
#userConfiguration: Record<string, unknown>
/**
* Initializes the Configurator.
* @param defaultValues - An object with the property values to use when not set in the userConfig.
* All keys should correspond to the value being returned.
* ex. { propertyOne: 5, 'propertyTwo.inner': 'value' }
* @param userConfiguration - The values that should be used when available.
* ex. { propertyOne: 7, propertyTwo: { inner: 'userValue' } }
*/
constructor(
defaultValues: D,
userConfiguration: Record<string, unknown> = {}
) {
this.#defaultValues = defaultValues
this.#userConfiguration = userConfiguration
}
/**
* Retrieves a property value, checking in the following order.
* - User configuration
* - Default values
* - Fallback value
* @param propertyName - The property key.
* @param fallbackValue - An optional value if the property is not found in the user configuration or the default values.
* @returns A property value.
*/
getConfigProperty<K extends keyof D>(
propertyName: K | string,
fallbackValue?: D[K]
): D[K] | undefined {
const userPropertyValue =
this.#getPropertyFromUserConfiguration(propertyName)
if (userPropertyValue.propertyFound) {
return userPropertyValue.propertyValue as D[K] | undefined
}
const defaultPropertyValue =
this.#getPropertyFromDefaultValues(propertyName)
if (defaultPropertyValue.propertyFound) {
return defaultPropertyValue.propertyValue as D[K] | undefined
}
return fallbackValue
}
/**
* Checks if the default value for the property has been overwritten with a different value in the user configuration.
* @param propertyName - The property key.
* @returns `true` if the user configuration has a different value compared to the default.
*/
isDefaultValueOverwritten(propertyName: keyof D): boolean {
const userPropertyValue =
this.#getPropertyFromUserConfiguration(propertyName)
if (!userPropertyValue.propertyFound) {
return false
}
const defaultPropertyValue =
this.#getPropertyFromDefaultValues(propertyName)
return (
!defaultPropertyValue.propertyFound ||
userPropertyValue.propertyValue !== defaultPropertyValue.propertyValue
)
}
/**
* Checks if the property has been set in the default values object.
* @param propertyName - The property key.
* @returns `true` if the property key is found in the default values object.
*/
isPropertyInDefaultValues(propertyName: string): boolean {
return this.#getPropertyFromDefaultValues(propertyName).propertyFound
}
/**
* Checks if the property has been set in the user configuration.
* @param propertyName - The property key.
* @returns `true` if the property key is found in the user configuration.
*/
isPropertyInUserConfig(propertyName: string): boolean {
return this.#getPropertyFromUserConfiguration(propertyName).propertyFound
}
/**
* Updates the user configuration.
* @param userConfiguration - The values that should be used when available.
* ex. { propertyOne: 7, propertyTwo: { inner: 'userValue' } }
*/
setUserConfig(userConfiguration: Record<string, unknown>): void {
this.#userConfiguration = userConfiguration
}
#getPropertyFromDefaultValues<K extends keyof D>(
propertyName: K
): PropertyValue<D[K]> {
if (Object.hasOwn(this.#defaultValues, propertyName)) {
return {
propertyFound: true,
propertyValue: this.#defaultValues[propertyName]
}
}
return {
propertyFound: false
}
}
#getPropertyFromUserConfiguration<K extends keyof D>(
propertyName: K
): PropertyValue<D[K]> {
/*
* If the propertyName is in the userConfig as is
* Return the value from the userConfig
*/
if (Object.hasOwn(this.#userConfiguration, propertyName)) {
return {
propertyFound: true,
propertyValue: (this.#userConfiguration as Record<K, unknown>)[
propertyName
] as D[K]
}
}
let currentObject: unknown = this.#userConfiguration
/*
* Split the propertyName and search the userConfig
*/
const propertyNameSplit = (propertyName as string).split('.')
for (const propertyNamePiece of propertyNameSplit) {
if (
typeof currentObject === 'object' &&
currentObject !== null &&
Object.hasOwn(currentObject, propertyNamePiece)
) {
currentObject = currentObject[propertyNamePiece]
continue
}
return {
propertyFound: false
}
}
return {
propertyFound: true,
propertyValue: currentObject as D[K]
}
}
}