From a1aa096535f9858de848e1ad87919fbfc0238a3e Mon Sep 17 00:00:00 2001 From: Hugo Tiger <49451774+hugotiger@users.noreply.github.com> Date: Mon, 23 Sep 2024 17:22:44 +0200 Subject: [PATCH] fix: Serialization of default values in `createSerializer` (#642) * fix: Handle `clearOnDefault` in `createSerializer` * chore: Fix types --------- Co-authored-by: Francois Best --- packages/nuqs/src/serializer.test.ts | 31 +++++++++++++++++++++++++++- packages/nuqs/src/serializer.ts | 9 ++++++-- 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/packages/nuqs/src/serializer.test.ts b/packages/nuqs/src/serializer.test.ts index f90ad52e..1115fd15 100644 --- a/packages/nuqs/src/serializer.test.ts +++ b/packages/nuqs/src/serializer.test.ts @@ -1,5 +1,11 @@ import { describe, expect, test } from 'vitest' -import { parseAsBoolean, parseAsInteger, parseAsString } from './parsers' +import { + parseAsArrayOf, + parseAsBoolean, + parseAsInteger, + parseAsJson, + parseAsString +} from './parsers' import { createSerializer } from './serializer' const parsers = { @@ -62,4 +68,27 @@ describe('serializer', () => { const result = serialize('?str=bar&int=-1', { str: 'foo', int: null }) expect(result).toBe('?str=foo') }) + test('clears value when setting the default value when `clearOnDefault` is used', () => { + const serialize = createSerializer({ + int: parseAsInteger.withOptions({ clearOnDefault: true }).withDefault(0), + str: parseAsString.withOptions({ clearOnDefault: true }).withDefault(''), + bool: parseAsBoolean + .withOptions({ clearOnDefault: true }) + .withDefault(false), + arr: parseAsArrayOf(parseAsString) + .withOptions({ clearOnDefault: true }) + .withDefault([]), + json: parseAsJson() + .withOptions({ clearOnDefault: true }) + .withDefault({ foo: 'bar' }) + }) + const result = serialize({ + int: 0, + str: '', + bool: false, + arr: [], + json: { foo: 'bar' } + }) + expect(result).toBe('') + }) }) diff --git a/packages/nuqs/src/serializer.ts b/packages/nuqs/src/serializer.ts index f2caf14c..8da2e65c 100644 --- a/packages/nuqs/src/serializer.ts +++ b/packages/nuqs/src/serializer.ts @@ -10,9 +10,10 @@ type Base = string | URLSearchParams | URL type Values>> = Partial<{ [K in keyof Parsers]?: ExtractParserType }> +type ParserWithOptionalDefault = ParserBuilder & { defaultValue?: T } export function createSerializer< - Parsers extends Record> + Parsers extends Record> >(parsers: Parsers) { /** * Generate a query string for the given values. @@ -41,7 +42,11 @@ export function createSerializer< if (!parser || value === undefined) { continue } - if (value === null) { + const isMatchingDefault = + parser.defaultValue !== undefined && + (parser.eq ?? ((a, b) => a === b))(value, parser.defaultValue) + + if (value === null || (parser.clearOnDefault && isMatchingDefault)) { search.delete(key) } else { search.set(key, parser.serialize(value))