75 lines
2.0 KiB
TypeScript
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
|
|
}
|
|
}
|