import type { ZodError, z } from 'zod' import { fromZodError } from 'zod-validation-error' import { GameConfigSchema } from './schemas' import { GameLogger } from '../GameLogger' type KeyOf = T extends object ? { [K in keyof T]-?: K | `${K & string}.${KeyOf & string}` }[keyof T] : never type ValueOf> = K extends `${infer U}.${infer R}` ? U extends keyof T ? ValueOf>> : never : K extends keyof T ? T[K] : never export type GameCoreConfig = z.infer export type GameConfigType = Record export class GameConfig { private static _config = {} as GameCoreConfig private static readonly _logger = new GameLogger('🛠️ GameConfig', false) private static _isValid = false public static init(config: GameConfigType): void { try { GameConfigSchema.parse(config) this._config = config as GameCoreConfig this._isValid = true } catch (error) { const validationError = fromZodError(error as ZodError, { issueSeparator: '\n', prefixSeparator: '', prefix: '' }) const lines = validationError.message.split('\n') const errors = lines .map((error, index) => { const shouldSkipLine = index === 0 && lines.length > 1 return (error = `${shouldSkipLine ? '\n\n' : ''}• ${error}`) }) .join('\n') this._isValid = false this._logger.error(errors) } } public static getValue>(key: K): ValueOf { if (Object.keys(GameConfig.current).length === 0) throw new Error('Cannot log this out') const keys = key.split('.') const value = keys.reduce((obj: any, key) => obj[key], this._config) // refactor!(): obj value changes but its type doesn't | temporary any type for now return value } public static get current(): GameCoreConfig { return this._config } public static get valid(): boolean { return this._isValid } }