Skip to content

Commit 230b7c7

Browse files
fix: correctly parse package name for scoped packages (#2135)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
1 parent 69dc57a commit 230b7c7

File tree

4 files changed

+97
-2
lines changed

4 files changed

+97
-2
lines changed

server/api/registry/analysis/[...pkg].get.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ export default defineCachedEventHandler(
4141

4242
try {
4343
const { packageName, version } = v.parse(PackageRouteParamsSchema, {
44-
packageName: rawPackageName,
44+
packageName: decodeURIComponent(rawPackageName),
4545
version: rawVersion,
4646
})
4747

server/api/registry/install-size/[...pkg].get.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ export default defineCachedEventHandler(
1818

1919
try {
2020
const { packageName, version: requestedVersion } = v.parse(PackageRouteParamsSchema, {
21-
packageName: rawPackageName,
21+
packageName: decodeURIComponent(rawPackageName),
2222
version: rawVersion,
2323
})
2424

test/e2e/interactions.spec.ts

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,48 @@ test.describe('Compare Page', () => {
4747
const noDepColumn = grid.locator('.comparison-cell-nodep')
4848
await expect(noDepColumn).toBeVisible()
4949
})
50+
51+
test('loads install-size data for a scoped package', async ({ page, goto }) => {
52+
// Intercept the internal API call the browser makes for install-size.
53+
// The browser will request /api/registry/install-size/@nuxt%2Fkit (encoded slash).
54+
// Before the fix this would fail to parse and return an error; after it returns 200.
55+
const installSizeResponse = page.waitForResponse(
56+
res =>
57+
res.url().includes('/api/registry/install-size/') &&
58+
res.url().includes('nuxt') &&
59+
res.request().method() === 'GET',
60+
{ timeout: 20_000 },
61+
)
62+
63+
await goto('/compare?packages=@nuxt/kit,vue', { waitUntil: 'hydration' })
64+
65+
const response = await installSizeResponse
66+
expect(response.status()).toBe(200)
67+
68+
const body = await response.json()
69+
// The API should return a valid install size object, not an error
70+
expect(body).toHaveProperty('selfSize')
71+
expect(body).toHaveProperty('totalSize')
72+
})
73+
74+
test('loads analysis data for a scoped package', async ({ page, goto }) => {
75+
const analysisResponse = page.waitForResponse(
76+
res =>
77+
res.url().includes('/api/registry/analysis/') &&
78+
res.url().includes('nuxt') &&
79+
res.request().method() === 'GET',
80+
{ timeout: 20_000 },
81+
)
82+
83+
await goto('/compare?packages=@nuxt/kit,vue', { waitUntil: 'hydration' })
84+
85+
const response = await analysisResponse
86+
expect(response.status()).toBe(200)
87+
88+
const body = await response.json()
89+
expect(body).toHaveProperty('package', '@nuxt/kit')
90+
expect(body).toHaveProperty('moduleFormat', 'esm')
91+
})
5092
})
5193

5294
test.describe('Search Pages', () => {
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import { describe, expect, it } from 'vitest'
2+
import { parsePackageParams } from '#server/utils/parse-package-params'
3+
4+
describe('parsePackageParams', () => {
5+
describe('unscoped packages', () => {
6+
it('parses package name without version', () => {
7+
const segments = ['vue']
8+
const result = parsePackageParams(segments)
9+
expect(result).toEqual({
10+
rawPackageName: 'vue',
11+
rawVersion: undefined,
12+
})
13+
})
14+
15+
it('parses package name with version', () => {
16+
const segments = ['vue', 'v', '3.4.0']
17+
const result = parsePackageParams(segments)
18+
expect(result).toEqual({
19+
rawPackageName: 'vue',
20+
rawVersion: '3.4.0',
21+
})
22+
})
23+
24+
it('parses package name with prerelease version', () => {
25+
const segments = ['nuxt', 'v', '4.0.0-rc.1']
26+
const result = parsePackageParams(segments)
27+
expect(result).toEqual({
28+
rawPackageName: 'nuxt',
29+
rawVersion: '4.0.0-rc.1',
30+
})
31+
})
32+
})
33+
34+
describe('scoped packages', () => {
35+
it('parses scoped package name without version', () => {
36+
const segments = ['@nuxt', 'kit']
37+
const result = parsePackageParams(segments)
38+
expect(result).toEqual({
39+
rawPackageName: '@nuxt/kit',
40+
rawVersion: undefined,
41+
})
42+
})
43+
44+
it('parses scoped package name with version', () => {
45+
const segments = ['@nuxt', 'kit', 'v', '1.0.0']
46+
const result = parsePackageParams(segments)
47+
expect(result).toEqual({
48+
rawPackageName: '@nuxt/kit',
49+
rawVersion: '1.0.0',
50+
})
51+
})
52+
})
53+
})

0 commit comments

Comments
 (0)