Skip to content

Commit

Permalink
fix: nextjs parallel routes with catchall isn't supported (#141)
Browse files Browse the repository at this point in the history
  • Loading branch information
feugy committed May 24, 2024
1 parent 74942cd commit cc5a474
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 12 deletions.
2 changes: 1 addition & 1 deletion packages/web/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@vercel/analytics",
"version": "1.3.0",
"version": "1.3.1",
"description": "Gain real-time traffic insights with Vercel Web Analytics",
"keywords": [
"analytics",
Expand Down
22 changes: 21 additions & 1 deletion packages/web/src/utils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -145,12 +145,21 @@ describe('utils', () => {
const input = '/en/us/next-site';
const params = {
langs: ['en', 'us'],
teamSlug: 'vercel',
};
const expected = '/[...langs]/next-site';
expect(computeRoute(input, params)).toBe(expected);
});

it('handles array segments and individual segments', () => {
const input = '/en/us/next-site';
const params = {
langs: ['en', 'us'],
team: 'next-site',
};
const expected = '/[...langs]/[team]';
expect(computeRoute(input, params)).toBe(expected);
});

it('handles special characters in url', () => {
const input = '/123/test(test';
const params = {
Expand All @@ -172,6 +181,17 @@ describe('utils', () => {
expect(computeRoute(input, params)).toBe(expected);
});

it('parallel routes where params matched both individually and within arrays', () => {
const params = {
catchAll: ['m', 'john', 'p', 'shirt'],
merchantId: 'john',
productSlug: 'shirt',
};
expect(computeRoute('/m/john/p/shirt', params)).toBe(
'/m/[merchantId]/p/[productSlug]'
);
});

describe('edge case handling (same values for multiple params)', () => {
it('replaces based on the priority of the pathParams keys', () => {
const input = '/test/test';
Expand Down
31 changes: 21 additions & 10 deletions packages/web/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,25 +83,36 @@ export function computeRoute(
}

let result = pathname;

try {
for (const [key, valueOrArray] of Object.entries(pathParams)) {
const isValueArray = Array.isArray(valueOrArray);
const value = isValueArray ? valueOrArray.join('/') : valueOrArray;
const expr = isValueArray ? `...${key}` : key;

const matcher = new RegExp(`/${escapeRegExp(value)}(?=[/?#]|$)`);
if (matcher.test(result)) {
result = result.replace(matcher, `/[${expr}]`);
const entries = Object.entries(pathParams);
// simple keys must be handled first
for (const [key, value] of entries) {
if (!Array.isArray(value)) {
const matcher = turnValueToRegExp(value);
if (matcher.test(result)) {
result = result.replace(matcher, `/[${key}]`);
}
}
}
// array values next
for (const [key, value] of entries) {
if (Array.isArray(value)) {
const matcher = turnValueToRegExp(value.join('/'));
if (matcher.test(result)) {
result = result.replace(matcher, `/[...${key}]`);
}
}
}

return result;
} catch (e) {
return pathname;
}
}

function turnValueToRegExp(value: string): RegExp {
return new RegExp(`/${escapeRegExp(value)}(?=[/?#]|$)`);
}

function escapeRegExp(string: string): string {
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
}

0 comments on commit cc5a474

Please sign in to comment.