]> git.ipfire.org Git - thirdparty/vuejs/router.git/commitdiff
refactor: adapt param parser types to work with queries
authorEduardo San Martin Morote <posva13@gmail.com>
Wed, 20 Aug 2025 09:39:25 +0000 (11:39 +0200)
committerEduardo San Martin Morote <posva13@gmail.com>
Wed, 20 Aug 2025 09:39:25 +0000 (11:39 +0200)
packages/router/src/experimental/route-resolver/matchers/matcher-pattern.test-d.ts
packages/router/src/experimental/route-resolver/matchers/param-parsers/index.ts
packages/router/src/experimental/route-resolver/matchers/param-parsers/numbers.ts
packages/router/src/experimental/route-resolver/matchers/param-parsers/types.ts

index de39f16752b24cc0e8d46a25dbf7ddbcbcd07d77..02f1c642f248b0758ba7a71e2b2605bf3c838cd0 100644 (file)
@@ -1,14 +1,14 @@
 import { describe, expectTypeOf, it } from 'vitest'
 import { MatcherPatternPathDynamic } from './matcher-pattern'
 import { PARAM_INTEGER_SINGLE } from './param-parsers/numbers'
-import { PATH_PARAM_DEFAULT_PARSER } from './param-parsers'
+import { PATH_PARAM_PARSER_DEFAULTS } from './param-parsers'
 import { PATH_PARAM_SINGLE_DEFAULT } from './param-parsers'
 
 describe('MatcherPatternPathCustomParams', () => {
   it('can be generic', () => {
     const matcher = new MatcherPatternPathDynamic(
       /^\/users\/([^/]+)$/i,
-      { userId: { ...PATH_PARAM_DEFAULT_PARSER } },
+      { userId: { ...PATH_PARAM_PARSER_DEFAULTS } },
       ['users', 0]
     )
 
index 89d4fcb445f3b4a19c273ac458b406bcc1f072ec..d7eadc3b480b725d056f8d2095ec3f7f65c60789 100644 (file)
@@ -13,19 +13,31 @@ export function defineParamParser<TOut, TIn extends string | string[]>(parser: {
   return parser
 }
 
-export const PATH_PARAM_DEFAULT_GET = (
-  value: string | string[] | null | undefined
-) => value ?? null
-export const PATH_PARAM_DEFAULT_SET = (
-  value: string | string[] | null | undefined
-) => (value && Array.isArray(value) ? value.map(String) : String(value)) // TODO: `(value an null | undefined)` for types
-
 export const PATH_PARAM_SINGLE_DEFAULT: ParamParser<string, string> = {}
-export const PATH_PARAM_DEFAULT_PARSER = {
-  get: PATH_PARAM_DEFAULT_GET,
-  set: PATH_PARAM_DEFAULT_SET,
+
+/**
+ * Default parser for params that will keep values as is, and will use `String()`
+ */
+export const PARAM_PARSER_DEFAULTS = {
+  get: value => value ?? null,
+  set: value =>
+    value == null
+      ? null
+      : Array.isArray(value)
+        ? value.map(v => (v == null ? null : String(v)))
+        : String(value),
 } satisfies ParamParser
 
+export const PATH_PARAM_PARSER_DEFAULTS = {
+  get: value => value ?? null,
+  set: value =>
+    value == null
+      ? null
+      : Array.isArray(value)
+        ? value.map(String)
+        : String(value),
+} satisfies ParamParser<string | string[] | null, string | string[] | null>
+
 export type { ParamParser }
 
 export { PARAM_PARSER_INT } from './numbers'
index 3fe9fa1fe92469006ebd652beef39eb21e025d0e..1386b1a56dc60280aafdf3a0e72fd3de18df194e 100644 (file)
@@ -2,7 +2,7 @@ import { miss } from '../errors'
 import { ParamParser } from './types'
 
 export const PARAM_INTEGER_SINGLE = {
-  get: (value: string) => {
+  get: (value: string | null) => {
     const num = Number(value)
     if (value && Number.isInteger(num)) {
       return num
@@ -10,7 +10,7 @@ export const PARAM_INTEGER_SINGLE = {
     throw miss()
   },
   set: (value: number) => String(value),
-} satisfies ParamParser<number, string>
+} satisfies ParamParser<number, string | null>
 
 export const PARAM_INTEGER_OPTIONAL = {
   get: (value: string | null) =>
@@ -20,9 +20,9 @@ export const PARAM_INTEGER_OPTIONAL = {
 } satisfies ParamParser<number | null, string | null>
 
 export const PARAM_INTEGER_REPEATABLE = {
-  get: (value: string[]) => value.map(PARAM_INTEGER_SINGLE.get),
+  get: (value: (string | null)[]) => value.map(PARAM_INTEGER_SINGLE.get),
   set: (value: number[]) => value.map(PARAM_INTEGER_SINGLE.set),
-} satisfies ParamParser<number[], string[]>
+} satisfies ParamParser<number[], (string | null)[]>
 
 export const PARAM_INTEGER_REPEATABLE_OPTIONAL = {
   get: (value: string[] | null) =>
index c4b65d270ff884f2561bbaa385cd361b9bc53632..59aea004b98e5bf6bd815f11103b8764b976db96 100644 (file)
@@ -1,3 +1,5 @@
+import { MatcherQueryParamsValue } from '../matcher-pattern'
+
 /**
  * Defines a parser that can read a param from the url (string-based) and
  * transform it into a more complex type, or vice versa.
@@ -5,13 +7,17 @@
  * @see MatcherPattern
  */
 export interface ParamParser<
-  TOut = string | string[] | null,
-  TIn extends string | string[] | null = string | string[] | null,
+  TOut = MatcherQueryParamsValue,
+  TIn extends MatcherQueryParamsValue = MatcherQueryParamsValue,
 > {
   get?: (value: NoInfer<TIn>) => TOut
   set?: (value: NoInfer<TOut>) => TIn
 }
 
+// TODO: I wonder if native param parsers should follow this or similar
+// these parsers can be used for both query and path params
+// export type ParamParserBoth<T> = ParamParser<T | T[] | null>
+
 /**
  * Generic type for a param parser that can handle both single and repeatable params.
  *