1- import type { NpmSearchResponse , NpmSearchResult , SearchProvider } from '#shared/types'
1+ import type {
2+ NpmSearchResponse ,
3+ NpmSearchResult ,
4+ SearchProvider ,
5+ SearchResponse ,
6+ SearchResult ,
7+ SearchSuggestion ,
8+ } from '#shared/types'
29import type { AlgoliaMultiSearchChecks } from './useAlgoliaSearch'
3- import { type SearchSuggestion , emptySearchResponse , parseSuggestionIntent } from './search-utils'
10+ import { emptySearchResponse , parseSuggestionIntent } from './search-utils'
411import { isValidNewPackageName , checkPackageExists } from '~/utils/package-name'
512
613export const SEARCH_ENGINE_HITS_LIMIT : Record < SearchProvider , number > = {
714 algolia : 1000 ,
815 npm : 5000 ,
916} as const
1017
11- function emptySearchPayload ( ) {
12- return {
13- searchResponse : emptySearchResponse ( ) ,
14- suggestions : [ ] as SearchSuggestion [ ] ,
15- packageAvailability : null as { name : string ; available : boolean } | null ,
16- }
17- }
18+ const DEFAULT_INITIAL_SEARCH_LIMIT = 25
1819
1920export interface SearchOptions {
2021 size ?: number
@@ -78,6 +79,25 @@ export function useSearch(
7879 }
7980 }
8081
82+ function prepareSearchResponse ( response : NpmSearchResponse | SearchResponse ) : SearchResponse {
83+ const totalUnlimited : number =
84+ 'totalUnlimited' in response ? response . totalUnlimited : response . total
85+
86+ return {
87+ ...response ,
88+ totalUnlimited,
89+ total : Math . min ( totalUnlimited , SEARCH_ENGINE_HITS_LIMIT [ toValue ( searchProvider ) ] ) ,
90+ }
91+ }
92+
93+ function emptySearchPayload ( ) : SearchResult {
94+ return {
95+ searchResponse : emptySearchResponse ( ) ,
96+ suggestions : [ ] ,
97+ packageAvailability : null ,
98+ }
99+ }
100+
81101 /**
82102 * Determine which extra checks to include in the Algolia multi-search.
83103 * Returns `undefined` when nothing uncached needs checking.
@@ -166,7 +186,7 @@ export function useSearch(
166186 suggestionsLoading . value = false
167187 }
168188
169- const asyncData = useLazyAsyncData (
189+ const asyncData = useLazyAsyncData < SearchResult > (
170190 ( ) => `search:${ toValue ( searchProvider ) } :${ toValue ( query ) } ` ,
171191 async ( _nuxtApp , { signal } ) => {
172192 const q = toValue ( query )
@@ -185,7 +205,11 @@ export function useSearch(
185205
186206 if ( config . suggestions ) {
187207 suggestionsLoading . value = true
188- const result = await algoliaMultiSearch ( q , { size : opts . size ?? 25 } , checks )
208+ const result = await algoliaMultiSearch (
209+ q ,
210+ { size : opts . size ?? DEFAULT_INITIAL_SEARCH_LIMIT } ,
211+ checks ,
212+ )
189213
190214 if ( q !== toValue ( query ) ) {
191215 return emptySearchPayload ( )
@@ -194,28 +218,32 @@ export function useSearch(
194218 isRateLimited . value = false
195219 processAlgoliaChecks ( q , checks , result )
196220 return {
197- searchResponse : result . search ,
221+ searchResponse : prepareSearchResponse ( result . search ) ,
198222 suggestions : suggestions . value ,
199223 packageAvailability : packageAvailability . value ,
200224 }
201225 }
202226
203- const response = await searchAlgolia ( q , { size : opts . size ?? 25 } )
227+ const response = await searchAlgolia ( q , { size : opts . size ?? DEFAULT_INITIAL_SEARCH_LIMIT } )
204228
205229 if ( q !== toValue ( query ) ) {
206230 return emptySearchPayload ( )
207231 }
208232
209233 isRateLimited . value = false
210234 return {
211- searchResponse : response ,
235+ searchResponse : prepareSearchResponse ( response ) ,
212236 suggestions : [ ] ,
213237 packageAvailability : null ,
214238 }
215239 }
216240
217241 try {
218- const response = await searchNpm ( q , { size : opts . size ?? 25 } , signal )
242+ const response = await searchNpm (
243+ q ,
244+ { size : opts . size ?? DEFAULT_INITIAL_SEARCH_LIMIT } ,
245+ signal ,
246+ )
219247
220248 if ( q !== toValue ( query ) ) {
221249 return emptySearchPayload ( )
@@ -225,7 +253,7 @@ export function useSearch(
225253
226254 isRateLimited . value = false
227255 return {
228- searchResponse : response ,
256+ searchResponse : prepareSearchResponse ( response ) ,
229257 suggestions : [ ] ,
230258 packageAvailability : null ,
231259 }
@@ -261,8 +289,7 @@ export function useSearch(
261289
262290 // Seed cache from asyncData for Algolia (which skips cache on initial fetch)
263291 if ( ! cache . value && asyncData . data . value ) {
264- const { searchResponse } = asyncData . data . value
265- setCache ( [ ...searchResponse . objects ] , searchResponse . total )
292+ setCache ( [ ...searchResponse . objects ] , searchResponse . totalUnlimited )
266293 }
267294
268295 const currentCount = cache . value ?. objects . length ?? 0
@@ -326,7 +353,7 @@ export function useSearch(
326353 } ,
327354 )
328355
329- const data = computed < NpmSearchResponse | null > ( ( ) => {
356+ const data = computed < SearchResponse | null > ( ( ) => {
330357 if ( cache . value ) {
331358 return {
332359 isStale : false ,
@@ -339,7 +366,7 @@ export function useSearch(
339366 return asyncData . data . value ?. searchResponse ?? null
340367 } )
341368
342- const hasMore = computed ( ( ) => {
369+ const hasMore = computed < boolean > ( ( ) => {
343370 if ( ! cache . value ) return true
344371 return cache . value . objects . length < cache . value . total
345372 } )
0 commit comments