11<script setup lang="ts">
22import type { FilterChip , SortKey } from ' #shared/types/preferences'
3- import { parseSortOption } from ' #shared/types/preferences'
3+ import { parseSortOption , PROVIDER_SORT_KEYS } from ' #shared/types/preferences'
44import { onKeyDown } from ' @vueuse/core'
55import { debounce } from ' perfect-debounce'
66import { isValidNewPackageName , checkPackageExists } from ' ~/utils/package-name'
@@ -111,8 +111,8 @@ const visibleResults = computed(() => {
111111// Use structured filters for client-side refinement of search results
112112const resultsArray = computed (() => visibleResults .value ?.objects ?? [])
113113
114- // Sort keys that the npm registry path doesn't support (only relevance works server-side)
115- const NON_RELEVANCE_SORT_KEYS : SortKey [] = [
114+ // All possible non- relevance sort keys
115+ const ALL_SORT_KEYS : SortKey [] = [
116116 ' downloads-week' ,
117117 ' downloads-day' ,
118118 ' downloads-month' ,
@@ -125,8 +125,11 @@ const NON_RELEVANCE_SORT_KEYS: SortKey[] = [
125125 ' score' ,
126126]
127127
128- // Disable non-relevance sorts when using npm provider (results are relevance-only from server)
129- const disabledSortKeys = computed <SortKey []>(() => (isAlgolia .value ? [] : NON_RELEVANCE_SORT_KEYS ))
128+ // Disable sort keys the current provider can't meaningfully sort by
129+ const disabledSortKeys = computed <SortKey []>(() => {
130+ const supported = PROVIDER_SORT_KEYS [isAlgolia .value ? ' algolia' : ' npm' ]
131+ return ALL_SORT_KEYS .filter (k => ! supported .has (k ))
132+ })
130133
131134// Minimal structured filters usage for search context (no client-side filtering)
132135const {
@@ -154,21 +157,29 @@ const isRelevanceSort = computed(
154157 () => sortOption .value === ' relevance-desc' || sortOption .value === ' relevance-asc' ,
155158)
156159
160+ // Maximum eager-load sizes per provider for client-side sorting.
161+ // Algolia supports up to 1000 with offset/length pagination.
162+ // npm supports pagination via `from` parameter (no hard cap, but diminishing relevance).
163+ const EAGER_LOAD_SIZE = { algolia: 500 , npm: 500 } as const
164+
157165// Calculate how many results we need based on current page and preferred page size
158166const requestedSize = computed (() => {
159167 const numericPrefSize = preferredPageSize .value === ' all' ? 250 : preferredPageSize .value
160168 const base = Math .max (pageSize , currentPage .value * numericPrefSize )
161- // When sorting by something other than relevance, fetch a large batch from Algolia
169+ // When sorting by something other than relevance, fetch a large batch
162170 // so client-side sorting operates on a meaningful pool of matching results
163171 if (! isRelevanceSort .value ) {
164- return Math .max (base , 250 )
172+ const cap = isAlgolia .value ? EAGER_LOAD_SIZE .algolia : EAGER_LOAD_SIZE .npm
173+ return Math .max (base , cap )
165174 }
166175 return base
167176})
168177
169- // Reset to relevance sort when switching to npm (which only supports relevance)
178+ // Reset to relevance sort when switching to a provider that doesn't support the current sort key
170179watch (isAlgolia , algolia => {
171- if (! algolia && ! isRelevanceSort .value ) {
180+ const { key } = parseSortOption (sortOption .value )
181+ const supported = PROVIDER_SORT_KEYS [algolia ? ' algolia' : ' npm' ]
182+ if (! supported .has (key )) {
172183 sortOption .value = ' relevance-desc'
173184 }
174185})
@@ -192,8 +203,8 @@ const displayResults = computed(() => {
192203 return resultsArray .value
193204 }
194205
195- // Sort the fetched results client-side ( Algolia doesn't support arbitrary
196- // sort orders without replica indices , so we fetch a large batch and sort here)
206+ // Sort the fetched results client-side — neither Algolia nor npm support
207+ // arbitrary sort orders server-side , so we fetch a large batch and sort here
197208 const { key, direction } = parseSortOption (sortOption .value )
198209 const multiplier = direction === ' asc' ? 1 : - 1
199210
@@ -212,6 +223,18 @@ const displayResults = computed(() => {
212223 case ' name' :
213224 diff = a .package .name .localeCompare (b .package .name )
214225 break
226+ case ' quality' :
227+ diff = (a .score ?.detail ?.quality ?? 0 ) - (b .score ?.detail ?.quality ?? 0 )
228+ break
229+ case ' popularity' :
230+ diff = (a .score ?.detail ?.popularity ?? 0 ) - (b .score ?.detail ?.popularity ?? 0 )
231+ break
232+ case ' maintenance' :
233+ diff = (a .score ?.detail ?.maintenance ?? 0 ) - (b .score ?.detail ?.maintenance ?? 0 )
234+ break
235+ case ' score' :
236+ diff = (a .score ?.final ?? 0 ) - (b .score ?.final ?? 0 )
237+ break
215238 default :
216239 diff = 0
217240 }
0 commit comments