(s: Schema<T, S>, dynamic = true)
| 150 | } |
| 151 | |
| 152 | requestConfig<T, S>(s: Schema<T, S>, dynamic = true): S { |
| 153 | if (!this.settings.includes(s)) { |
| 154 | this.ctx.effect(() => { |
| 155 | logger.debug('Loading config', s); |
| 156 | this.settings.push(s); |
| 157 | this._applySchema(); |
| 158 | return () => { |
| 159 | logger.debug('Unloading config', s); |
| 160 | this.settings = this.settings.filter((v) => v !== s); |
| 161 | this._applySchema(); |
| 162 | }; |
| 163 | }); |
| 164 | } |
| 165 | let curValue = s(this.systemConfig); |
| 166 | if (!dynamic) return curValue; |
| 167 | this.ctx.on('system/setting', () => { |
| 168 | try { |
| 169 | curValue = s(this.systemConfig); |
| 170 | } catch (e) { |
| 171 | logger.warn('Cannot read config: ', e.message); |
| 172 | curValue = null; |
| 173 | } |
| 174 | }); |
| 175 | const that = this; |
| 176 | const getAccess = (path: (string | symbol)[]) => { |
| 177 | if (path.some((p) => SettingService.blacklist.includes(p.toString()))) throw new Error(`Invalid path: ${path.join('.')}`); |
| 178 | let currentValue = curValue; |
| 179 | for (const p of path) currentValue = currentValue[p]; |
| 180 | if ((typeof currentValue !== 'object') || !currentValue || Array.isArray(currentValue)) return currentValue; |
| 181 | if (path.some((p) => typeof p === 'symbol')) return currentValue; |
| 182 | return new Proxy(currentValue, { |
| 183 | get(self, key: string) { |
| 184 | return getAccess([...path, key]); |
| 185 | }, |
| 186 | set(self, p: string | symbol, newValue: any) { |
| 187 | that.setConfig([...path, p].join(','), newValue); |
| 188 | return true; |
| 189 | }, |
| 190 | }); |
| 191 | }; |
| 192 | return getAccess([]); |
| 193 | } |
| 194 | } |
no test coverage detected