Skip to content

Commit 480877c

Browse files
committed
feat: normalize param parsers once
1 parent 2f729f6 commit 480877c

3 files changed

Lines changed: 132 additions & 16 deletions

File tree

packages/router/src/unplugin/codegen/generateParamParsers.spec.ts

Lines changed: 106 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
generateParamParserOptions,
88
generatePathParamsOptions,
99
generateCustomParamParsersList,
10+
generateNormalizedParamParsersDeclarations,
1011
type ParamParsersMap,
1112
} from './generateParamParsers'
1213
import { PrefixTree } from '../core/tree'
@@ -385,10 +386,9 @@ describe('generateParamParserOptions', () => {
385386
])
386387

387388
const result = generateParamParserOptions(param, importsMap, paramParsers)
388-
expect(result).toBe('_normalizeParamParser(PARAM_PARSER__uuid)')
389-
expect(importsMap.toString()).toContain(
390-
`import { parser as PARAM_PARSER__uuid } from '/path/to/parsers/uuid'`
391-
)
389+
expect(result).toBe('_normalized_PARAM_PARSER__uuid')
390+
// imports are no longer added by generateParamParserOptions for custom parsers
391+
// they are handled by generateNormalizedParamParsersDeclarations
392392
})
393393

394394
it('generates correct import for native int parser', () => {
@@ -562,7 +562,7 @@ describe('generatePathParamsOptions', () => {
562562
])
563563

564564
const result = generatePathParamsOptions(params, importsMap, paramParsers)
565-
expect(result).toContain('id: [_normalizeParamParser(PARAM_PARSER__uuid)]')
565+
expect(result).toContain('id: [_normalized_PARAM_PARSER__uuid]')
566566
expect(result).toContain(
567567
'page: [PARAM_PARSER_INT, /* repeatable: false */, /* optional: */ true]'
568568
)
@@ -676,16 +676,112 @@ describe('generateParamParserCustomType', () => {
676676
parser: 'user-id', // Route uses original kebab-case name
677677
}
678678
expect(generateParamParserOptions(param, importsMap, paramParsers)).toBe(
679-
'_normalizeParamParser(PARAM_PARSER__userId)'
679+
'_normalized_PARAM_PARSER__userId'
680680
) // Generated variable is camelCase
681-
682-
expect(importsMap.toString()).toContain(
683-
`import { parser as PARAM_PARSER__userId } from '/path/to/parsers/user-id'`
684-
)
681+
// imports are no longer added by generateParamParserOptions for custom parsers
685682

686683
expect(generateCustomParamParsersList(paramParsers)).toEqual([
687684
"'date-with-dashes'",
688685
"'user-id'",
689686
])
690687
})
691688
})
689+
690+
describe('generateNormalizedParamParsersDeclarations', () => {
691+
it('returns empty string for empty param parsers map', () => {
692+
const paramParsers: ParamParsersMap = new Map()
693+
const importsMap = new ImportsMap()
694+
const result = generateNormalizedParamParsersDeclarations(
695+
paramParsers,
696+
importsMap
697+
)
698+
expect(result).toBe('')
699+
})
700+
701+
it('generates a const declaration for a single parser', () => {
702+
const paramParsers: ParamParsersMap = new Map([
703+
[
704+
'uuid',
705+
{
706+
name: 'uuid',
707+
typeName: 'Param_uuid',
708+
relativePath: 'parsers/uuid',
709+
absolutePath: '/path/to/parsers/uuid',
710+
},
711+
],
712+
])
713+
const importsMap = new ImportsMap()
714+
const result = generateNormalizedParamParsersDeclarations(
715+
paramParsers,
716+
importsMap
717+
)
718+
expect(result).toBe(
719+
'const _normalized_PARAM_PARSER__uuid = _normalizeParamParser(PARAM_PARSER__uuid)'
720+
)
721+
expect(importsMap.toString()).toContain(
722+
`import { _normalizeParamParser } from 'vue-router/experimental'`
723+
)
724+
expect(importsMap.toString()).toContain(
725+
`import { parser as PARAM_PARSER__uuid } from '/path/to/parsers/uuid'`
726+
)
727+
})
728+
729+
it('generates declarations for multiple parsers', () => {
730+
const paramParsers: ParamParsersMap = new Map([
731+
[
732+
'uuid',
733+
{
734+
name: 'uuid',
735+
typeName: 'Param_uuid',
736+
relativePath: 'parsers/uuid',
737+
absolutePath: '/path/to/parsers/uuid',
738+
},
739+
],
740+
[
741+
'slug',
742+
{
743+
name: 'slug',
744+
typeName: 'Param_slug',
745+
relativePath: 'parsers/slug',
746+
absolutePath: '/path/to/parsers/slug',
747+
},
748+
],
749+
])
750+
const importsMap = new ImportsMap()
751+
const result = generateNormalizedParamParsersDeclarations(
752+
paramParsers,
753+
importsMap
754+
)
755+
expect(result).toContain(
756+
'const _normalized_PARAM_PARSER__uuid = _normalizeParamParser(PARAM_PARSER__uuid)'
757+
)
758+
expect(result).toContain(
759+
'const _normalized_PARAM_PARSER__slug = _normalizeParamParser(PARAM_PARSER__slug)'
760+
)
761+
})
762+
763+
it('handles camelCase names from kebab-case filenames', () => {
764+
const paramParsers: ParamParsersMap = new Map([
765+
[
766+
'user-id',
767+
{
768+
name: 'userId',
769+
typeName: 'Param_userId',
770+
relativePath: 'parsers/user-id',
771+
absolutePath: '/path/to/parsers/user-id',
772+
},
773+
],
774+
])
775+
const importsMap = new ImportsMap()
776+
const result = generateNormalizedParamParsersDeclarations(
777+
paramParsers,
778+
importsMap
779+
)
780+
expect(result).toBe(
781+
'const _normalized_PARAM_PARSER__userId = _normalizeParamParser(PARAM_PARSER__userId)'
782+
)
783+
expect(importsMap.toString()).toContain(
784+
`import { parser as PARAM_PARSER__userId } from '/path/to/parsers/user-id'`
785+
)
786+
})
787+
})

packages/router/src/unplugin/codegen/generateParamParsers.ts

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -105,11 +105,8 @@ export function generateParamParserOptions(
105105

106106
// we prioritize custom parsers to let users override them
107107
if (paramParsers.has(param.parser)) {
108-
const { name, absolutePath } = paramParsers.get(param.parser)!
109-
const varName = `PARAM_PARSER__${name}`
110-
importsMap.add('vue-router/experimental', '_normalizeParamParser')
111-
importsMap.add(absolutePath, { name: 'parser', as: varName })
112-
return `_normalizeParamParser(${varName})`
108+
const { name } = paramParsers.get(param.parser)!
109+
return `_normalized_PARAM_PARSER__${name}`
113110
} else if (NATIVE_PARAM_PARSERS.includes(param.parser)) {
114111
const varName = `PARAM_PARSER_${param.parser.toUpperCase()}`
115112
importsMap.add('vue-router/experimental', varName)
@@ -118,6 +115,23 @@ export function generateParamParserOptions(
118115
return ''
119116
}
120117

118+
export function generateNormalizedParamParsersDeclarations(
119+
paramParsers: ParamParsersMap,
120+
importsMap: ImportsMap
121+
): string {
122+
const declarations: string[] = []
123+
for (const [, { name, absolutePath }] of paramParsers) {
124+
const rawVar = `PARAM_PARSER__${name}`
125+
const normalizedVar = `_normalized_PARAM_PARSER__${name}`
126+
importsMap.add('vue-router/experimental', '_normalizeParamParser')
127+
importsMap.add(absolutePath, { name: 'parser', as: rawVar })
128+
declarations.push(
129+
`const ${normalizedVar} = _normalizeParamParser(${rawVar})`
130+
)
131+
}
132+
return declarations.join('\n')
133+
}
134+
121135
export function generateCustomParamParsersList(
122136
paramParsers: ParamParsersMap
123137
): string[] {

packages/router/src/unplugin/codegen/generateRouteResolver.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { toStringLiteral, ts } from '../utils'
66
import {
77
generatePathParamsOptions,
88
generateParamParserOptions,
9+
generateNormalizedParamParsersDeclarations,
910
ParamParsersMap,
1011
} from './generateParamParsers'
1112
import { generatePageImport, formatMeta } from './generateRouteRecords'
@@ -95,8 +96,13 @@ export function generateRouteResolver(
9596
importsMap.add('vue-router/experimental', 'MatcherPatternPathDynamic')
9697
importsMap.add('vue-router/experimental', 'normalizeRouteRecord')
9798

99+
const normalizedDeclarations = generateNormalizedParamParsersDeclarations(
100+
paramParsersMap,
101+
importsMap
102+
)
103+
98104
return ts`
99-
${records.join('\n\n')}
105+
${normalizedDeclarations ? normalizedDeclarations + '\n\n' : ''}${records.join('\n\n')}
100106
101107
export const resolver = createFixedResolver([
102108
${state.matchableRecords

0 commit comments

Comments
 (0)