Skip to content

Commit 96d8a89

Browse files
committed
fix: handle subsegments
1 parent 40930f3 commit 96d8a89

File tree

2 files changed

+51
-10
lines changed

2 files changed

+51
-10
lines changed

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

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,4 +217,26 @@ describe('MatcherPatternPathCustom', () => {
217217
'/teams/123/456'
218218
)
219219
})
220+
221+
it('sub segments (params + static)', () => {
222+
const pattern = new MatcherPatternPathCustomParams(
223+
/^\/teams\/([^/]+?)-b-([^/]+?)$/i,
224+
{
225+
teamId: {},
226+
otherId: {},
227+
},
228+
['teams', [0, '-b-', 0]]
229+
)
230+
231+
expect(pattern.match('/teams/123-b-456')).toEqual({
232+
teamId: '123',
233+
otherId: '456',
234+
})
235+
expect(() => pattern.match('/teams/123-b')).toThrow()
236+
expect(() => pattern.match('/teams/123-b-456/c')).toThrow()
237+
expect(() => pattern.match('/teams/')).toThrow()
238+
expect(pattern.build({ teamId: '123', otherId: '456' })).toBe(
239+
'/teams/123-b-456'
240+
)
241+
})
220242
})

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

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,7 @@ export class MatcherPatternPathCustomParams<
291291
// A better version could be using all the parts to join them
292292
// .e.g ['users', 0, 'profile', 1] -> /users/123/profile/456
293293
// numbers are indexes of the params in the params object keys
294-
readonly pathParts: Array<string | number>
294+
readonly pathParts: Array<string | number | Array<string | number>>
295295
) {
296296
this.paramsKeys = Object.keys(this.params) as Array<keyof TParamsOptions>
297297
}
@@ -335,16 +335,35 @@ export class MatcherPatternPathCustomParams<
335335
.map(part => {
336336
if (typeof part === 'string') {
337337
return part
338+
} else if (typeof part === 'number') {
339+
const paramName = this.paramsKeys[paramIndex++]
340+
const paramOptions = this.params[paramName]
341+
const value: ReturnType<NonNullable<ParamParser['set']>> = (
342+
paramOptions.set || identityFn
343+
)(params[paramName])
344+
345+
return Array.isArray(value)
346+
? value.map(encodeParam).join('/')
347+
: encodeParam(value)
348+
} else {
349+
return part
350+
.map(subPart => {
351+
if (typeof subPart === 'string') {
352+
return subPart
353+
}
354+
355+
const paramName = this.paramsKeys[paramIndex++]
356+
const paramOptions = this.params[paramName]
357+
const value: ReturnType<NonNullable<ParamParser['set']>> = (
358+
paramOptions.set || identityFn
359+
)(params[paramName])
360+
361+
return Array.isArray(value)
362+
? value.map(encodeParam).join('/')
363+
: encodeParam(value)
364+
})
365+
.join('')
338366
}
339-
const paramName = this.paramsKeys[paramIndex++]
340-
const paramOptions = this.params[paramName]
341-
const value: ReturnType<NonNullable<ParamParser['set']>> = (
342-
paramOptions.set || identityFn
343-
)(params[paramName])
344-
345-
return Array.isArray(value)
346-
? value.map(encodeParam).join('/')
347-
: encodeParam(value)
348367
})
349368
.filter(identityFn) // filter out empty values
350369
.join('/')

0 commit comments

Comments
 (0)