From 17b0625a731966d3671af28beb00ad7e743109c1 Mon Sep 17 00:00:00 2001 From: Marcel Date: Fri, 12 Jun 2026 19:45:22 +0200 Subject: [PATCH] fix(shared): null-harden settled() against placeholder slots A Promise.resolve(null) placeholder (e.g. the gated drafts slot) fulfils with a null value; settled() dereferenced v.response unconditionally and threw. Now any nullish value resolves to null. Adds unit tests for all settled() branches. Co-Authored-By: Claude Fable 5 --- .../src/lib/shared/server/settled.test.ts | 37 +++++++++++++++++++ frontend/src/lib/shared/server/settled.ts | 4 +- 2 files changed, 39 insertions(+), 2 deletions(-) create mode 100644 frontend/src/lib/shared/server/settled.test.ts diff --git a/frontend/src/lib/shared/server/settled.test.ts b/frontend/src/lib/shared/server/settled.test.ts new file mode 100644 index 00000000..26ca88ec --- /dev/null +++ b/frontend/src/lib/shared/server/settled.test.ts @@ -0,0 +1,37 @@ +import { describe, expect, it } from 'vitest'; +import { settled } from './settled'; + +describe('settled', () => { + it('returns the data for a fulfilled ok response', () => { + const res: PromiseSettledResult = { + status: 'fulfilled', + value: { response: { ok: true } as Response, data: [{ id: '1' }] } + }; + expect(settled<{ id: string }[]>(res)).toEqual([{ id: '1' }]); + }); + + it('returns null for a fulfilled non-ok response', () => { + const res: PromiseSettledResult = { + status: 'fulfilled', + value: { response: { ok: false, status: 403 } as Response, data: undefined } + }; + expect(settled(res)).toBeNull(); + }); + + it('returns null for a rejected result', () => { + const res: PromiseSettledResult = { + status: 'rejected', + reason: new Error('network error') + }; + expect(settled(res)).toBeNull(); + }); + + it('returns null for undefined input', () => { + expect(settled(undefined)).toBeNull(); + }); + + it('returns null for a fulfilled null value (Promise.resolve(null) placeholder slot)', () => { + const res: PromiseSettledResult = { status: 'fulfilled', value: null }; + expect(settled(res)).toBeNull(); + }); +}); diff --git a/frontend/src/lib/shared/server/settled.ts b/frontend/src/lib/shared/server/settled.ts index 2fe321b8..41dde16d 100644 --- a/frontend/src/lib/shared/server/settled.ts +++ b/frontend/src/lib/shared/server/settled.ts @@ -1,5 +1,5 @@ export function settled(res: PromiseSettledResult | undefined): T | null { if (res?.status !== 'fulfilled') return null; - const v = res.value as { response: Response; data: unknown }; - return v.response.ok ? ((v.data as T) ?? null) : null; + const v = res.value as { response: Response; data: unknown } | null; + return v?.response?.ok ? ((v.data as T) ?? null) : null; }