From 3646b9cc339c05140571027bc131af85470e31d1 Mon Sep 17 00:00:00 2001 From: Eduardo San Martin Morote Date: Sun, 24 Aug 2025 22:07:44 +0200 Subject: [PATCH] feat: inverse spalt and other params in MatcherPatternPathdynamic --- .../src/router/index.ts | 2 +- .../matchers/matcher-pattern.spec.ts | 24 +++++++++---------- .../matchers/matcher-pattern.test-d.ts | 6 ++--- .../matchers/matcher-pattern.ts | 10 ++++---- .../router/src/experimental/router.spec.ts | 10 ++++---- 5 files changed, 27 insertions(+), 25 deletions(-) diff --git a/packages/experiments-playground/src/router/index.ts b/packages/experiments-playground/src/router/index.ts index f53fb6a4..3f9c1bb3 100644 --- a/packages/experiments-playground/src/router/index.ts +++ b/packages/experiments-playground/src/router/index.ts @@ -121,7 +121,7 @@ const r_profiles_detail = normalizeRouteRecord({ // and therefore userId is of type number userId: PARAM_PARSER_INT, }, - ['profiles', 0] + ['profiles', 1] ), }) diff --git a/packages/router/src/experimental/route-resolver/matchers/matcher-pattern.spec.ts b/packages/router/src/experimental/route-resolver/matchers/matcher-pattern.spec.ts index cc31a765..cf509784 100644 --- a/packages/router/src/experimental/route-resolver/matchers/matcher-pattern.spec.ts +++ b/packages/router/src/experimental/route-resolver/matchers/matcher-pattern.spec.ts @@ -134,7 +134,7 @@ describe('MatcherPatternPathDynamic', () => { // all defaults teamId: {}, }, - ['teams', 0, 'b'] + ['teams', 1, 'b'] ) expect(pattern.match('/teams/123/b')).toEqual({ @@ -155,7 +155,7 @@ describe('MatcherPatternPathDynamic', () => { { teamId: {}, }, - ['teams', 0] + ['teams', 1] ) expect(pattern.match('/teams/a%20b')).toEqual({ teamId: 'a b' }) expect(pattern.build({ teamId: 'a b' })).toBe('/teams/a%20b') @@ -167,7 +167,7 @@ describe('MatcherPatternPathDynamic', () => { { teamId: {}, }, - ['teams', 0, 'b'] + ['teams', 1, 'b'] ) expect(pattern.match('/teams/b')).toEqual({ teamId: null }) @@ -186,7 +186,7 @@ describe('MatcherPatternPathDynamic', () => { { teamId: {}, }, - ['teams', 0, 'b'] + ['teams', 1, 'b'] ) expect(pattern.match('/teams/b')).toEqual({ teamId: null }) @@ -205,7 +205,7 @@ describe('MatcherPatternPathDynamic', () => { { teamId: { repeat: true }, }, - ['teams', 0, 'b'] + ['teams', 1, 'b'] ) expect(pattern.match('/teams/123/b')).toEqual({ teamId: ['123'] }) @@ -228,7 +228,7 @@ describe('MatcherPatternPathDynamic', () => { { pathMatch: {}, }, - ['teams', 1] + ['teams', 0] ) expect(pattern.match('/teams/')).toEqual({ pathMatch: '' }) expect(pattern.match('/teams/123/b')).toEqual({ pathMatch: '123/b' }) @@ -247,7 +247,7 @@ describe('MatcherPatternPathDynamic', () => { { teamId: { repeat: true }, }, - ['teams', 0, 'b'] + ['teams', 1, 'b'] ) expect(pattern.match('/teams/123/b')).toEqual({ teamId: ['123'] }) @@ -271,7 +271,7 @@ describe('MatcherPatternPathDynamic', () => { teamId: {}, otherId: {}, }, - ['teams', 0, 0] + ['teams', 1, 1] ) expect(pattern.match('/teams/123/456')).toEqual({ @@ -293,7 +293,7 @@ describe('MatcherPatternPathDynamic', () => { teamId: {}, otherId: {}, }, - ['teams', [0, '-b-', 0]] + ['teams', [1, '-b-', 1]] ) expect(pattern.match('/teams/123-b-456')).toEqual({ @@ -314,7 +314,7 @@ describe('MatcherPatternPathDynamic', () => { { teamId: {}, }, - ['teams', [0, '/']] + ['teams', [1, '/']] ) expect(pattern.match('/teams/123/')).toEqual({ @@ -345,7 +345,7 @@ describe('MatcherPatternPathDynamic', () => { { teamId: { repeat: true }, }, - ['teams', [0, '/']] + ['teams', [1, '/']] ) expect(pattern.match('/teams/123/')).toEqual({ teamId: ['123'] }) @@ -365,7 +365,7 @@ describe('MatcherPatternPathDynamic', () => { { teamId: { repeat: true }, }, - ['teams', [0, '/']] + ['teams', [1, '/']] ) expect(pattern.match('/teams/123/')).toEqual({ teamId: ['123'] }) diff --git a/packages/router/src/experimental/route-resolver/matchers/matcher-pattern.test-d.ts b/packages/router/src/experimental/route-resolver/matchers/matcher-pattern.test-d.ts index 30dd53ff..ac515b10 100644 --- a/packages/router/src/experimental/route-resolver/matchers/matcher-pattern.test-d.ts +++ b/packages/router/src/experimental/route-resolver/matchers/matcher-pattern.test-d.ts @@ -9,7 +9,7 @@ describe('MatcherPatternPathDynamic', () => { const matcher = new MatcherPatternPathDynamic( /^\/users\/([^/]+)$/i, { userId: { ...PATH_PARAM_PARSER_DEFAULTS } }, - ['users', 0] + ['users', 1] ) expectTypeOf(matcher.match('/users/123')).toEqualTypeOf<{ @@ -34,7 +34,7 @@ describe('MatcherPatternPathDynamic', () => { const matcher = new MatcherPatternPathDynamic( /^\/users\/([^/]+)\/([^/]+)$/i, { userId: { ...PATH_PARAM_SINGLE_DEFAULT, repeat: true } }, - ['users', 0] + ['users', 1] ) expectTypeOf(matcher.match('/users/123/456')).toEqualTypeOf<{ userId: string @@ -57,7 +57,7 @@ describe('MatcherPatternPathDynamic', () => { // parser: PATH_PARAM_DEFAULT_PARSER, }, }, - ['profiles', 0] + ['profiles', 1] ) expectTypeOf(matcher.match('/profiles/2')).toEqualTypeOf<{ diff --git a/packages/router/src/experimental/route-resolver/matchers/matcher-pattern.ts b/packages/router/src/experimental/route-resolver/matchers/matcher-pattern.ts index c797711a..f59086ef 100644 --- a/packages/router/src/experimental/route-resolver/matchers/matcher-pattern.ts +++ b/packages/router/src/experimental/route-resolver/matchers/matcher-pattern.ts @@ -137,7 +137,7 @@ export class MatcherPatternPathDynamic< // otherwise, we need to use a factory function: https://github.com/microsoft/TypeScript/issues/40451 readonly params: TParamsOptions & Record>, - // 0 means a regular param, 1 means a splat, the order comes from the keys in params + // 1 means a regular param, 0 means a splat, the order comes from the keys in params readonly pathParts: Array> ) { this.paramsKeys = Object.keys(this.params) as Array @@ -198,8 +198,8 @@ export class MatcherPatternPathDynamic< return Array.isArray(value) ? value.map(encodeParam).join('/') - : // part == 0 means a regular param, 1 means a splat - (part /* part !== 0 */ ? encodePath : encodeParam)(value) + : // part == 1 means a regular param, 0 means a splat + (part ? encodeParam : encodePath)(value) } else { return part .map(subPart => { @@ -235,7 +235,9 @@ export class MatcherPatternPathDynamic< * with the original splat path: e.g. /teams/[...pathMatch] does not match /teams, so it makes * no sense to build a path it cannot match. */ - return lastParamPart && !value ? path + '/' : path + return !lastParamPart /** lastParamPart == 0 */ && !value + ? path + '/' + : path } } diff --git a/packages/router/src/experimental/router.spec.ts b/packages/router/src/experimental/router.spec.ts index c97bcd0d..358e46e4 100644 --- a/packages/router/src/experimental/router.spec.ts +++ b/packages/router/src/experimental/router.spec.ts @@ -55,25 +55,25 @@ import { mockWarn } from '../../__tests__/vitest-mock-warn' const paramMatcher = new MatcherPatternPathDynamic( /^\/p\/([^/]+)$/, { p: {} }, - ['p', 0] + ['p', 1] ) const optionalMatcher = new MatcherPatternPathDynamic( /^\/optional(?:\/([^/]+))?$/, { p: {} }, - ['optional', 0] + ['optional', 1] ) const repeatMatcher = new MatcherPatternPathDynamic( /^\/repeat\/(.+)$/, { r: { repeat: true } }, - ['repeat', 1] + ['repeat', 0] ) const catchAllMatcher = new MatcherPatternPathDynamic( /^\/(.*)$/, { pathMatch: { repeat: true } }, - [1] + [0] ) // Create experimental route records using proper structure @@ -380,7 +380,7 @@ describe('Experimental Router', () => { const testCatchAllMatcher = new MatcherPatternPathDynamic( /^\/(.*)$/, { pathMatch: { repeat: true } }, - [1] + [0] ) const catchAllRecord = normalizeRouteRecord({ name: 'notfound', -- 2.47.3