From 234ecbffcf4f0bcf8ca62bc3fb401f08aed9b8c5 Mon Sep 17 00:00:00 2001 From: Ferdinand Thiessen Date: Fri, 1 Aug 2025 16:59:59 +0200 Subject: [PATCH] fix: return fallback if value cannot be parsed If there is a fallback we should handle this error more gracefully. We report it in the console, but return the fallback if provided. Otherwise we just throw as before. Signed-off-by: Ferdinand Thiessen --- eslint.config.js | 10 +++++++++- lib/index.ts | 5 +++++ test/index.test.ts | 28 ++++++++++++++++++++++++++++ 3 files changed, 42 insertions(+), 1 deletion(-) diff --git a/eslint.config.js b/eslint.config.js index 817f4585..522f74a4 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -6,4 +6,12 @@ import { recommendedLibrary } from '@nextcloud/eslint-config' import { defineConfig } from 'eslint/config' -export default defineConfig([...recommendedLibrary]) +export default defineConfig([ + ...recommendedLibrary, + { + rules: { + // this is quite a lowlevel library without dependencies - so no dependency on the logger + 'no-console': 'off', + }, + }, +]) diff --git a/lib/index.ts b/lib/index.ts index af2e686e..89d2e12d 100644 --- a/lib/index.ts +++ b/lib/index.ts @@ -31,6 +31,11 @@ export function loadState(app: string, key: string, fallback?: T): T { window._nc_initial_state.set(selector, parsedValue) return parsedValue } catch (error) { + console.error('[@nextcloud/initial-state] Could not parse initial state', { key, app, error }) + + if (fallback !== undefined) { + return fallback + } throw new Error(`Could not parse initial state ${key} of ${app}`, { cause: error }) } } diff --git a/test/index.test.ts b/test/index.test.ts index 6f67d267..e45b96fe 100644 --- a/test/index.test.ts +++ b/test/index.test.ts @@ -46,3 +46,31 @@ test('returns cached value with consequent calls', () => { expect(JSON.parse).toHaveBeenCalledTimes(1) }) + +test('throws if state cannot be parsed and no fallback is provided', () => { + const errorLog = vi.spyOn(console, 'error') + errorLog.mockImplementationOnce(() => {}) + + appendInput('app', 'key', 'value') + const spy = vi.spyOn(JSON, 'parse') + spy.mockImplementationOnce(() => { + throw new Error('mocked parsing exception') + }) + + expect(() => loadState('app', 'key')).toThrowError('Could not parse initial state key of app') + expect(errorLog).toHaveBeenCalledOnce() +}) + +test('returns fallback if state cannot be parsed but fallback is provided', () => { + const errorLog = vi.spyOn(console, 'error') + errorLog.mockImplementationOnce(() => {}) + + appendInput('app', 'key', 'value') + const spy = vi.spyOn(JSON, 'parse') + spy.mockImplementationOnce(() => { + throw new Error('mocked parsing exception') + }) + + expect(loadState('app', 'key', 'fallback')).toBe('fallback') + expect(errorLog).toHaveBeenCalledOnce() +})