From 5e583b02c5dedffb095d916ef01db8a3661bee5e Mon Sep 17 00:00:00 2001 From: Francois Best Date: Mon, 8 Jan 2024 23:59:23 +0100 Subject: [PATCH] feat: Add validation support (Zod & others) --- packages/nuqs/src/parsers.ts | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/packages/nuqs/src/parsers.ts b/packages/nuqs/src/parsers.ts index 98b68dae5..409c7cbca 100644 --- a/packages/nuqs/src/parsers.ts +++ b/packages/nuqs/src/parsers.ts @@ -17,6 +17,27 @@ export type ParserBuilder = Required> & */ withOptions(this: This, options: Options): This + /** + * Pass in a validation function to perform runtime checks on the parsed + * value. If the validation fails, the value will be set to `null` (or + * the default value if specified). + * + * Validation must be synchronous, and must throw an error on invalid + * inputs. + * + * Example with Zod: + * ```ts + * const [posInt, setPosInt] = useQueryState( + * 'value', + * parseAsInteger.withValidation(z.number().positive().parse) + * ) + * ``` + * + * @param this + * @param validate + */ + withValidation(this: This, validate: (input: unknown) => T): This + /** * Specifying a default value makes the hook state non-nullable when the * query is missing from the URL. @@ -93,6 +114,18 @@ export function createParser(parser: Required>): ParserBuilder { return { ...parser, parseServerSide: parseServerSideNullable, + withValidation(validate) { + return { + ...this, + parse: (value: string) => { + const parsed = parser.parse(value) + if (parsed === null) { + return null + } + return validate(parsed) + } + } + }, withDefault(defaultValue) { return { ...this, @@ -102,7 +135,7 @@ export function createParser(parser: Required>): ParserBuilder { } } }, - withOptions(options: Options) { + withOptions(options) { return { ...this, ...options