Skip to content

Commit b876b4a

Browse files
committed
refactor: adapt param parser types to work with queries
1 parent 8bcf9de commit b876b4a

File tree

4 files changed

+36
-18
lines changed

4 files changed

+36
-18
lines changed

packages/router/src/experimental/route-resolver/matchers/matcher-pattern.test-d.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
import { describe, expectTypeOf, it } from 'vitest'
22
import { MatcherPatternPathDynamic } from './matcher-pattern'
33
import { PARAM_INTEGER_SINGLE } from './param-parsers/numbers'
4-
import { PATH_PARAM_DEFAULT_PARSER } from './param-parsers'
4+
import { PATH_PARAM_PARSER_DEFAULTS } from './param-parsers'
55
import { PATH_PARAM_SINGLE_DEFAULT } from './param-parsers'
66

77
describe('MatcherPatternPathCustomParams', () => {
88
it('can be generic', () => {
99
const matcher = new MatcherPatternPathDynamic(
1010
/^\/users\/([^/]+)$/i,
11-
{ userId: { ...PATH_PARAM_DEFAULT_PARSER } },
11+
{ userId: { ...PATH_PARAM_PARSER_DEFAULTS } },
1212
['users', 0]
1313
)
1414

packages/router/src/experimental/route-resolver/matchers/param-parsers/index.ts

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,19 +13,31 @@ export function defineParamParser<TOut, TIn extends string | string[]>(parser: {
1313
return parser
1414
}
1515

16-
export const PATH_PARAM_DEFAULT_GET = (
17-
value: string | string[] | null | undefined
18-
) => value ?? null
19-
export const PATH_PARAM_DEFAULT_SET = (
20-
value: string | string[] | null | undefined
21-
) => (value && Array.isArray(value) ? value.map(String) : String(value)) // TODO: `(value an null | undefined)` for types
22-
2316
export const PATH_PARAM_SINGLE_DEFAULT: ParamParser<string, string> = {}
24-
export const PATH_PARAM_DEFAULT_PARSER = {
25-
get: PATH_PARAM_DEFAULT_GET,
26-
set: PATH_PARAM_DEFAULT_SET,
17+
18+
/**
19+
* Default parser for params that will keep values as is, and will use `String()`
20+
*/
21+
export const PARAM_PARSER_DEFAULTS = {
22+
get: value => value ?? null,
23+
set: value =>
24+
value == null
25+
? null
26+
: Array.isArray(value)
27+
? value.map(v => (v == null ? null : String(v)))
28+
: String(value),
2729
} satisfies ParamParser
2830

31+
export const PATH_PARAM_PARSER_DEFAULTS = {
32+
get: value => value ?? null,
33+
set: value =>
34+
value == null
35+
? null
36+
: Array.isArray(value)
37+
? value.map(String)
38+
: String(value),
39+
} satisfies ParamParser<string | string[] | null, string | string[] | null>
40+
2941
export type { ParamParser }
3042

3143
export { PARAM_PARSER_INT } from './numbers'

packages/router/src/experimental/route-resolver/matchers/param-parsers/numbers.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,15 @@ import { miss } from '../errors'
22
import { ParamParser } from './types'
33

44
export const PARAM_INTEGER_SINGLE = {
5-
get: (value: string) => {
5+
get: (value: string | null) => {
66
const num = Number(value)
77
if (value && Number.isInteger(num)) {
88
return num
99
}
1010
throw miss()
1111
},
1212
set: (value: number) => String(value),
13-
} satisfies ParamParser<number, string>
13+
} satisfies ParamParser<number, string | null>
1414

1515
export const PARAM_INTEGER_OPTIONAL = {
1616
get: (value: string | null) =>
@@ -20,9 +20,9 @@ export const PARAM_INTEGER_OPTIONAL = {
2020
} satisfies ParamParser<number | null, string | null>
2121

2222
export const PARAM_INTEGER_REPEATABLE = {
23-
get: (value: string[]) => value.map(PARAM_INTEGER_SINGLE.get),
23+
get: (value: (string | null)[]) => value.map(PARAM_INTEGER_SINGLE.get),
2424
set: (value: number[]) => value.map(PARAM_INTEGER_SINGLE.set),
25-
} satisfies ParamParser<number[], string[]>
25+
} satisfies ParamParser<number[], (string | null)[]>
2626

2727
export const PARAM_INTEGER_REPEATABLE_OPTIONAL = {
2828
get: (value: string[] | null) =>

packages/router/src/experimental/route-resolver/matchers/param-parsers/types.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,23 @@
1+
import { MatcherQueryParamsValue } from '../matcher-pattern'
2+
13
/**
24
* Defines a parser that can read a param from the url (string-based) and
35
* transform it into a more complex type, or vice versa.
46
*
57
* @see MatcherPattern
68
*/
79
export interface ParamParser<
8-
TOut = string | string[] | null,
9-
TIn extends string | string[] | null = string | string[] | null,
10+
TOut = MatcherQueryParamsValue,
11+
TIn extends MatcherQueryParamsValue = MatcherQueryParamsValue,
1012
> {
1113
get?: (value: NoInfer<TIn>) => TOut
1214
set?: (value: NoInfer<TOut>) => TIn
1315
}
1416

17+
// TODO: I wonder if native param parsers should follow this or similar
18+
// these parsers can be used for both query and path params
19+
// export type ParamParserBoth<T> = ParamParser<T | T[] | null>
20+
1521
/**
1622
* Generic type for a param parser that can handle both single and repeatable params.
1723
*

0 commit comments

Comments
 (0)