Skip to content

Commit e824db5

Browse files
committed
feat: type custom params
1 parent b7aeacb commit e824db5

File tree

7 files changed

+139
-1
lines changed

7 files changed

+139
-1
lines changed

client.d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,11 @@ declare module 'vue-router/auto-routes' {
3434

3535
declare module 'vue-router' {
3636
import type { RouteNamedMap } from 'vue-router/auto-routes'
37+
import type { ParamParserCustom } from 'vue-router/auto-resolver'
3738

3839
export interface TypesConfig {
3940
RouteNamedMap: RouteNamedMap
41+
ParamParsers: ParamParserCustom
4042
}
4143
}
4244

playground-experimental/typed-router.d.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@
88
// Custom route params parsers
99
type Param_date = ReturnType<NonNullable<typeof import('./src/params/date.ts').parser['get']>>
1010

11+
declare module 'vue-router/auto-resolver' {
12+
export type ParamParserCustom = 'date'
13+
}
14+
1115
declare module 'vue-router/auto-routes' {
1216
import type {
1317
RouteRecordInfo,

playground/typed-router.d.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@
55
// It's recommended to commit this file.
66
// Make sure to add this file to your tsconfig.json file as an "includes" or "files" entry.
77

8+
declare module 'vue-router/auto-resolver' {
9+
export type ParamParserCustom = never
10+
}
11+
812
declare module 'vue-router/auto-routes' {
913
import type {
1014
RouteRecordInfo,

src/codegen/generateDTS.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,13 @@ export function generateDTS({
2020
routeNamedMap,
2121
routeFileInfoMap,
2222
paramsTypesDeclaration,
23+
customParamsType,
2324
}: {
2425
routesModule: string
2526
routeNamedMap: string
2627
routeFileInfoMap: string
2728
paramsTypesDeclaration: string
29+
customParamsType: string
2830
}) {
2931
return ts`
3032
/* eslint-disable */
@@ -42,7 +44,11 @@ ${paramsTypesDeclaration}
4244
4345
`.trimStart()
4446
: ''
45-
}declare module '${routesModule}' {
47+
}declare module 'vue-router/auto-resolver' {
48+
export type ParamParserCustom = ${customParamsType}
49+
}
50+
51+
declare module '${routesModule}' {
4652
import type {
4753
RouteRecordInfo,
4854
ParamValue,

src/codegen/generateParamParsers.spec.ts

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
generateParamsTypes,
66
generateParamParserOptions,
77
generatePathParamsOptions,
8+
generateParamParserCustomType,
89
type ParamParsersMap,
910
} from './generateParamParsers'
1011
import { PrefixTree } from '../core/tree'
@@ -464,3 +465,106 @@ describe('generatePathParamsOptions', () => {
464465
expect(result).toContain('tags: [/* no parser */, /* repeatable: */ true]')
465466
})
466467
})
468+
469+
describe('generateParamParserCustomType', () => {
470+
it('returns never for empty param parsers map', () => {
471+
const paramParsers: ParamParsersMap = new Map()
472+
const result = generateParamParserCustomType(paramParsers)
473+
expect(result).toBe('never')
474+
})
475+
476+
it('returns single quoted parser name for one parser', () => {
477+
const paramParsers: ParamParsersMap = new Map([
478+
[
479+
'date',
480+
{
481+
name: 'date',
482+
typeName: 'Param_date',
483+
relativePath: 'parsers/date',
484+
absolutePath: '/path/to/parsers/date',
485+
},
486+
],
487+
])
488+
489+
const result = generateParamParserCustomType(paramParsers)
490+
expect(result).toBe("'date'")
491+
})
492+
493+
it('returns union of quoted parser names for multiple parsers in alphabetical order on separate lines', () => {
494+
const paramParsers: ParamParsersMap = new Map([
495+
[
496+
'uuid',
497+
{
498+
name: 'uuid',
499+
typeName: 'Param_uuid',
500+
relativePath: 'parsers/uuid',
501+
absolutePath: '/path/to/parsers/uuid',
502+
},
503+
],
504+
[
505+
'date',
506+
{
507+
name: 'date',
508+
typeName: 'Param_date',
509+
relativePath: 'parsers/date',
510+
absolutePath: '/path/to/parsers/date',
511+
},
512+
],
513+
])
514+
515+
const result = generateParamParserCustomType(paramParsers)
516+
expect(result).toBe(" | 'date'\n | 'uuid'")
517+
})
518+
519+
it('handles parser names with special characters correctly', () => {
520+
const paramParsers: ParamParsersMap = new Map([
521+
[
522+
'custom-parser',
523+
{
524+
name: 'custom-parser',
525+
typeName: 'Param_custom-parser',
526+
relativePath: 'parsers/custom-parser',
527+
absolutePath: '/path/to/parsers/custom-parser',
528+
},
529+
],
530+
])
531+
532+
const result = generateParamParserCustomType(paramParsers)
533+
expect(result).toBe("'custom-parser'")
534+
})
535+
536+
it('formats multiple parsers with proper indentation for three or more types', () => {
537+
const paramParsers: ParamParsersMap = new Map([
538+
[
539+
'uuid',
540+
{
541+
name: 'uuid',
542+
typeName: 'Param_uuid',
543+
relativePath: 'parsers/uuid',
544+
absolutePath: '/path/to/parsers/uuid',
545+
},
546+
],
547+
[
548+
'date',
549+
{
550+
name: 'date',
551+
typeName: 'Param_date',
552+
relativePath: 'parsers/date',
553+
absolutePath: '/path/to/parsers/date',
554+
},
555+
],
556+
[
557+
'slug',
558+
{
559+
name: 'slug',
560+
typeName: 'Param_slug',
561+
relativePath: 'parsers/slug',
562+
absolutePath: '/path/to/parsers/slug',
563+
},
564+
],
565+
])
566+
567+
const result = generateParamParserCustomType(paramParsers)
568+
expect(result).toBe(" | 'date'\n | 'slug'\n | 'uuid'")
569+
})
570+
})

src/codegen/generateParamParsers.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,22 @@ export function generateParamParserOptions(
8787
return ''
8888
}
8989

90+
export function generateParamParserCustomType(
91+
paramParsers: ParamParsersMap
92+
): string {
93+
const parserNames = Array.from(paramParsers.keys()).sort()
94+
95+
if (parserNames.length === 0) {
96+
return 'never'
97+
}
98+
99+
if (parserNames.length === 1) {
100+
return `'${parserNames[0]}'`
101+
}
102+
103+
return parserNames.map((name) => ` | '${name}'`).join('\n')
104+
}
105+
90106
export function generatePathParamsOptions(
91107
params: TreePathParam[],
92108
importsMap: ImportsMap,

src/core/context.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import { generateRouteResolver } from '../codegen/generateRouteResolver'
2525
import { type FSWatcher, watch as fsWatch } from 'chokidar'
2626
import {
2727
generateParamParsersTypesDeclarations,
28+
generateParamParserCustomType,
2829
ParamParsersMap,
2930
warnMissingParamParsers,
3031
} from '../codegen/generateParamParsers'
@@ -370,6 +371,7 @@ if (import.meta.hot) {
370371
}),
371372
paramsTypesDeclaration:
372373
generateParamParsersTypesDeclarations(paramParsersMap),
374+
customParamsType: generateParamParserCustomType(paramParsersMap),
373375
})
374376

375377
// TODO: parser auto copmlete for definePage

0 commit comments

Comments
 (0)