game-engine/todo/GameConfig.ts

75 lines
2.0 KiB
TypeScript

import type { ZodError, z } from 'zod'
import { fromZodError } from 'zod-validation-error'
import { GameConfigSchema } from './schemas'
import { GameLogger } from '../GameLogger'
type KeyOf<T> = T extends object
? {
[K in keyof T]-?: K | `${K & string}.${KeyOf<T[K]> & string}`
}[keyof T]
: never
type ValueOf<T, K extends KeyOf<T>> = K extends `${infer U}.${infer R}`
? U extends keyof T
? ValueOf<T[U], Extract<R, KeyOf<T[U]>>>
: never
: K extends keyof T
? T[K]
: never
export type GameCoreConfig = z.infer<typeof GameConfigSchema>
export type GameConfigType = Record<string, any>
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<K extends KeyOf<GameCoreConfig>>(key: K): ValueOf<GameCoreConfig, K> {
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
}
}