Skip to content

Commit 4533bdb

Browse files
committed
fix: correct route query parsing for multiple params
1 parent 0df32a3 commit 4533bdb

File tree

5 files changed

+24
-15
lines changed

5 files changed

+24
-15
lines changed

app/components/Header/SearchBox.vue

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
<script setup lang="ts">
22
import { debounce } from 'perfect-debounce'
3+
import { normalizeSearchParam } from '#shared/utils/url'
34
45
withDefaults(
56
defineProps<{
@@ -22,9 +23,7 @@ const showSearchBar = computed(() => {
2223
})
2324
2425
// Local input value (updates immediately as user types)
25-
const searchQuery = shallowRef(
26-
(Array.isArray(route.query.q) ? route.query.q[0] : route.query.q) ?? '',
27-
)
26+
const searchQuery = shallowRef(normalizeSearchParam(route.query.q))
2827
2928
// Pages that have their own local filter using ?q
3029
const pagesWithLocalFilter = new Set(['~username', 'org'])
@@ -64,7 +63,7 @@ watch(
6463
if (pagesWithLocalFilter.has(route.name as string)) {
6564
return
6665
}
67-
const value = (urlQuery as string) ?? ''
66+
const value = normalizeSearchParam(urlQuery)
6867
if (searchQuery.value !== value) {
6968
searchQuery.value = value
7069
}

app/pages/@[org].vue

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<script setup lang="ts">
22
import type { FilterChip, SortOption } from '#shared/types/preferences'
33
import { debounce } from 'perfect-debounce'
4+
import { normalizeSearchParam } from '#shared/utils/url'
45
56
definePageMeta({
67
name: 'org',
@@ -51,9 +52,9 @@ const {
5152
} = useStructuredFilters({
5253
packages,
5354
initialFilters: {
54-
text: (route.query.q as string) ?? '',
55+
text: normalizeSearchParam(route.query.q),
5556
},
56-
initialSort: (route.query.sort as SortOption) ?? 'updated-desc',
57+
initialSort: (normalizeSearchParam(route.query.sort) as SortOption) ?? 'updated-desc',
5758
})
5859
5960
// Pagination state

app/pages/search.vue

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { onKeyDown } from '@vueuse/core'
44
import { debounce } from 'perfect-debounce'
55
import { isValidNewPackageName, checkPackageExists } from '~/utils/package-name'
66
import { isPlatformSpecificPackage } from '~/utils/platform-packages'
7+
import { normalizeSearchParam } from '#shared/utils/url'
78
89
const route = useRoute()
910
const router = useRouter()
@@ -29,7 +30,7 @@ const updateUrlPage = debounce((page: number) => {
2930
}, 500)
3031
3132
// The actual search query (from URL, used for API calls)
32-
const query = computed(() => (route.query.q as string) ?? '')
33+
const query = computed(() => normalizeSearchParam(route.query.q))
3334
3435
// Track if page just loaded (for hiding "Searching..." during view transition)
3536
const hasInteracted = shallowRef(false)
@@ -53,7 +54,7 @@ const requestedSize = computed(() => {
5354
5455
// Get initial page from URL (for scroll restoration on reload)
5556
const initialPage = computed(() => {
56-
const p = Number.parseInt(route.query.page as string, 10)
57+
const p = Number.parseInt(normalizeSearchParam(route.query.page), 10)
5758
return Number.isNaN(p) ? 1 : Math.max(1, p)
5859
})
5960

app/pages/~[username]/index.vue

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
<script setup lang="ts">
22
import { debounce } from 'perfect-debounce'
3+
import { normalizeSearchParam } from '#shared/utils/url'
34
45
const route = useRoute('~username')
56
const router = useRouter()
@@ -13,7 +14,7 @@ const currentPage = shallowRef(1)
1314
1415
// Get initial page from URL (for scroll restoration on reload)
1516
const initialPage = computed(() => {
16-
const p = Number.parseInt(route.query.page as string, 10)
17+
const p = Number.parseInt(normalizeSearchParam(route.query.page), 10)
1718
return Number.isNaN(p) ? 1 : Math.max(1, p)
1819
})
1920
@@ -32,18 +33,16 @@ const updateUrl = debounce((updates: { page?: number; filter?: string; sort?: st
3233
type SortOption = 'downloads' | 'updated' | 'name-asc' | 'name-desc'
3334
3435
// Filter and sort state (from URL)
35-
const filterText = shallowRef(
36-
(Array.isArray(route.query.q) ? route.query.q[0] : route.query.q) ?? '',
37-
)
36+
const filterText = shallowRef(normalizeSearchParam(route.query.q))
3837
const sortOption = shallowRef<SortOption>(
39-
((Array.isArray(route.query.sort) ? route.query.sort[0] : route.query.sort) as SortOption) ||
40-
'downloads',
38+
(normalizeSearchParam(route.query.sort) as SortOption) || 'downloads',
4139
)
4240
4341
// Track if we've loaded all results (one-way flag, doesn't reset)
4442
// Initialize to true if URL already has filter/sort params
4543
const hasLoadedAll = shallowRef(
46-
Boolean(route.query.q) || (route.query.sort && route.query.sort !== 'downloads'),
44+
Boolean(route.query.q) ||
45+
(route.query.sort && normalizeSearchParam(route.query.sort) !== 'downloads'),
4746
)
4847
4948
// Update URL when filter/sort changes (debounced)

shared/utils/url.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import type { LocationQueryValue } from 'vue-router'
12
import { withoutProtocol, withoutTrailingSlash } from 'ufo'
23

34
/**
@@ -25,3 +26,11 @@ export function normalizeUrlForComparison(url: string): string {
2526
export function areUrlsEquivalent(url1: string, url2: string): boolean {
2627
return normalizeUrlForComparison(url1) === normalizeUrlForComparison(url2)
2728
}
29+
30+
export function normalizeSearchParam(query?: LocationQueryValue | LocationQueryValue[]): string {
31+
if (!query) return ''
32+
33+
if (typeof query === 'string') return query
34+
35+
return normalizeSearchParam(query[0])
36+
}

0 commit comments

Comments
 (0)