type StringKeyOf = Extract; type SettingDefinition = { display: string; type: string; default?: unknown; }; export type SettingsSchema = Record< string, Record> >; const settings = { account: { profile: {}, security: { login_qr_code: { display: "Login QR Code", type: "custom", }, }, }, accessability: { chat: { reverse_enter_behavior: { display: "Reverse Enter Behavior", type: "boolean", default: false, }, read_confirmations: { display: "Enable Read Confirmations", type: "boolean", default: true, }, receive_confirmations: { display: "Enable Receive Confirmations", type: "boolean", default: false, }, show_start_of_last_message_in_sidebar: { display: "Show Start of Last Message in Sidebar", type: "boolean", default: true, }, }, }, call: { call: { call_jingle: { display: "Jingle", type: "select", default: "jingle_1" as "jingle_1" | "jingle_2", }, }, }, application: { cache: {}, theme: {}, licenses: {}, }, } as const satisfies SettingsSchema; // Assemble storage defaults export default settings; type SettingStorageEntry = { [C in StringKeyOf]: { [P in StringKeyOf]: { [S in StringKeyOf]: T[C][P][S] extends { default: infer V } ? { key: `settings.${S}`; value: V } : never; }[StringKeyOf]; }[StringKeyOf]; }[StringKeyOf]; type Widen = T extends boolean ? boolean : T extends string ? string extends T ? string : T : T extends number ? number : T; export type SettingsStorageKey = SettingStorageEntry["key"]; export type SettingsStorageDefaults< T extends SettingsSchema = typeof settings, > = { [K in SettingsStorageKey]: Widen< Extract, { key: K }>["value"] >; }; function buildSettingsStorageDefaults( schema: T, ): SettingsStorageDefaults { const defaults: Partial> = {}; for (const category of Object.values(schema)) { for (const page of Object.values(category)) { for (const [settingName, setting] of Object.entries(page)) { if ("default" in setting) { const key = `settings.${settingName}` as SettingsStorageKey; defaults[key] = setting.default as SettingsStorageDefaults[typeof key]; } } } } return defaults as SettingsStorageDefaults; } export const settingsStorageDefaults = buildSettingsStorageDefaults(settings);