From c785ad552c51ec86e334e354eaf356647be004fd Mon Sep 17 00:00:00 2001 From: Jakob Scheid Date: Wed, 5 Aug 2026 01:29:04 +0200 Subject: [PATCH] feat(settings): make setting value function synchronous Added a store to cache the settings configuration. The getSetting function from useSettings is now synchronous and uses this cache. The settings cache is set when loading the settings initially (asnychronously). --- .../composables/__tests__/useSettings.test.js | 91 +++++++++---------- .../settings/composables/useSettings.js | 5 +- .../stores/settingsConfigCacheStore.js | 31 +++++++ src/features/settings/utils/settingsParser.js | 3 + 4 files changed, 82 insertions(+), 48 deletions(-) create mode 100644 src/features/settings/stores/settingsConfigCacheStore.js diff --git a/src/features/settings/composables/__tests__/useSettings.test.js b/src/features/settings/composables/__tests__/useSettings.test.js index b6637fe..772467c 100644 --- a/src/features/settings/composables/__tests__/useSettings.test.js +++ b/src/features/settings/composables/__tests__/useSettings.test.js @@ -14,17 +14,58 @@ See the License for the specific language governing permissions and limitations under the License. */ +import { useSettingsConfigCacheStore } from '../../stores/settingsConfigCacheStore'; import { useSettingsStore } from '../../stores/settingsStore'; import { useSettings } from '../useSettings'; import { createTestingPinia } from '@pinia/testing'; import { setActivePinia } from 'pinia'; import { beforeEach, describe, expect, test, vi } from 'vitest'; -const settingDefaultValue = vi.hoisted(() => 42); -const settingPath = vi.hoisted(() => ['test', 'number']); +const settingDefaultValue = 42; +const settingPath = ['test', 'number']; -vi.mock('../../utils/settingsParser', () => ({ - loadSettingsConfig: vi.fn().mockResolvedValue({ +describe('useSettings', () => { + describe('getSetting', () => { + test('returns stored value', () => { + const { getSetting } = useSettings(); + const settings = useSettingsStore(); + + const key = 'setting'; + const value = 42; + + settings.set(key, value); + + expect(getSetting(key)).toBe(value); + }); + + test('returns default value', () => { + const { getSetting } = useSettings(); + expect(getSetting(settingPath)).toBe(settingDefaultValue); + }); + + test('returns stored value instead of default value', () => { + const { getSetting } = useSettings(); + const settings = useSettingsStore(); + + const value = 43; + + expect(getSetting(settingPath)).toBe(settingDefaultValue); + + settings.set(settingPath, value); + expect(getSetting(settingPath)).toBe(value); + }); + }); +}); + +beforeEach(() => { + setActivePinia( + createTestingPinia({ + createSpy: vi.fn, + stubActions: false + }) + ); + const settingsConfigCache = useSettingsConfigCacheStore(); + settingsConfigCache.set({ contents: [ { name: 'test', @@ -39,47 +80,5 @@ vi.mock('../../utils/settingsParser', () => ({ ] } ] - }) -})); - -describe('useSettings', () => { - describe('getSetting', () => { - test('returns stored value', async () => { - const { getSetting } = useSettings(); - const settings = useSettingsStore(); - - const key = 'setting'; - const value = 42; - - settings.set(key, value); - - expect(await getSetting(key)).toBe(value); - }); - - test('returns default value', async () => { - const { getSetting } = useSettings(); - expect(await getSetting(settingPath)).toBe(settingDefaultValue); - }); - - test('returns stored value instead of default value', async () => { - const { getSetting } = useSettings(); - const settings = useSettingsStore(); - - const value = 43; - - expect(await getSetting(settingPath)).toBe(settingDefaultValue); - - settings.set(settingPath, value); - expect(await getSetting(settingPath)).toBe(value); - }); }); }); - -beforeEach(() => { - setActivePinia( - createTestingPinia({ - createSpy: vi.fn, - stubActions: false - }) - ); -}); diff --git a/src/features/settings/composables/useSettings.js b/src/features/settings/composables/useSettings.js index f37102c..cd8cc29 100644 --- a/src/features/settings/composables/useSettings.js +++ b/src/features/settings/composables/useSettings.js @@ -14,6 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ +import { useSettingsConfigCacheStore } from '../stores/settingsConfigCacheStore'; import { useSettingsStore } from '../stores/settingsStore'; import { getSettingRecursively } from '../utils/getSetting'; import { loadSettingsConfig } from '../utils/settingsParser'; @@ -27,10 +28,10 @@ export const useSettings = function useSettings () { * @param {string[]} key - The settings key. * @return The value of the setting. */ - const getSetting = async function getSetting (key) { + const getSetting = function getSetting (key) { const settingsStore = useSettingsStore(); - const settings = await loadSettingsConfig(); + const settings = useSettingsConfigCacheStore().get(); return ( settingsStore.get(key) ?? getSettingRecursively( diff --git a/src/features/settings/stores/settingsConfigCacheStore.js b/src/features/settings/stores/settingsConfigCacheStore.js new file mode 100644 index 0000000..9ed923f --- /dev/null +++ b/src/features/settings/stores/settingsConfigCacheStore.js @@ -0,0 +1,31 @@ +/* +Copyright 2026 Seekra + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import { defineStore } from 'pinia'; + +export const useSettingsConfigCacheStore = defineStore('settingsConfigCache', () => { + let settingsConfig = undefined; + + const set = function set (value) { + settingsConfig = value; + }; + + const get = function get () { + return settingsConfig; + }; + + return { set, get }; +}); diff --git a/src/features/settings/utils/settingsParser.js b/src/features/settings/utils/settingsParser.js index 2b7e658..1dd9626 100644 --- a/src/features/settings/utils/settingsParser.js +++ b/src/features/settings/utils/settingsParser.js @@ -14,6 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ +import { useSettingsConfigCacheStore } from '../stores/settingsConfigCacheStore'; import { validateSettingsConfig } from './settingsValidator.js'; /** @@ -21,10 +22,12 @@ import { validateSettingsConfig } from './settingsValidator.js'; * @returns {Promise} */ export async function loadSettingsConfig() { + const settingsConfigCache = useSettingsConfigCacheStore(); let raw; try { raw = (await import('../settings.json')).default; + settingsConfigCache.set(raw); } catch (e) { throw new Error(`[settings] Failed to load settings.json: ${e.message}`); }