@@ -52,7 +52,7 @@ export function useSearch(
5252 const suggestionsLoading = shallowRef ( false )
5353 const packageAvailability = shallowRef < { name : string ; available : boolean } | null > ( null )
5454 const existenceCache = shallowRef < Record < string , boolean > > ( { } )
55- let suggestionRequestId = 0
55+ const suggestionRequestId = shallowRef ( 0 )
5656
5757 /**
5858 * Determine which extra checks to include in the Algolia multi-search.
@@ -225,23 +225,6 @@ export function useSearch(
225225 { default : emptySearchPayload } ,
226226 )
227227
228- watch (
229- [ ( ) => asyncData . data . value . suggestions , ( ) => suggestions . value ] ,
230- ( [ payloadSuggestions , localSuggestions ] ) => {
231- if ( ! payloadSuggestions . length && ! localSuggestions . length ) return
232- suggestions . value = payloadSuggestions . length ? payloadSuggestions : localSuggestions
233- } ,
234- { immediate : true } ,
235- )
236-
237- watch (
238- [ ( ) => asyncData . data . value ?. packageAvailability , ( ) => packageAvailability . value ] ,
239- ( [ payloadPackageAvailability , localPackageAvailability ] ) => {
240- packageAvailability . value = payloadPackageAvailability || localPackageAvailability
241- } ,
242- { immediate : true } ,
243- )
244-
245228 async function fetchMore ( targetSize : number ) : Promise < void > {
246229 const q = toValue ( query ) . trim ( )
247230 const provider = searchProvider . value
@@ -346,118 +329,140 @@ export function useSearch(
346329 return asyncData . data . value ?. searchResponse ?? null
347330 } )
348331
349- if ( import . meta. client && asyncData . data . value ?. searchResponse . isStale ) {
350- onMounted ( ( ) => {
351- asyncData . refresh ( )
352- } )
353- }
354-
355332 const hasMore = computed ( ( ) => {
356333 if ( ! cache . value ) return true
357334 return cache . value . objects . length < cache . value . total
358335 } )
359336
360- // npm suggestion checking (Algolia handles suggestions inside the search handler above)
361- if ( config . suggestions ) {
362- async function validateSuggestionsNpm ( q : string ) {
363- const requestId = ++ suggestionRequestId
364- const { intent, name } = parseSuggestionIntent ( q )
365-
366- const trimmed = q . trim ( )
367- if ( isValidNewPackageName ( trimmed ) ) {
368- checkPackageExists ( trimmed )
369- . then ( exists => {
370- if ( trimmed === toValue ( query ) . trim ( ) ) {
371- packageAvailability . value = { name : trimmed , available : ! exists }
372- }
373- } )
374- . catch ( ( ) => {
375- packageAvailability . value = null
376- } )
377- } else {
378- packageAvailability . value = null
379- }
337+ async function validateSuggestionsNpm ( q : string ) {
338+ const requestId = ++ suggestionRequestId . value
339+ const { intent, name } = parseSuggestionIntent ( q )
340+ let availability : { name : string ; available : boolean } | null = null
380341
381- if ( ! intent || ! name ) {
382- suggestions . value = [ ]
383- suggestionsLoading . value = false
384- return
385- }
342+ const trimmed = q . trim ( )
343+ if ( isValidNewPackageName ( trimmed ) ) {
344+ checkPackageExists ( trimmed )
345+ . then ( exists => {
346+ if ( trimmed === toValue ( query ) . trim ( ) ) {
347+ availability = { name : trimmed , available : ! exists }
348+ packageAvailability . value = availability
349+ }
350+ } )
351+ . catch ( ( ) => {
352+ availability = null
353+ } )
354+ } else {
355+ availability = null
356+ }
386357
387- suggestionsLoading . value = true
388- const result : SearchSuggestion [ ] = [ ]
389- const lowerName = name . toLowerCase ( )
358+ if ( ! intent || ! name ) {
359+ suggestionsLoading . value = false
360+ return { suggestions : [ ] , packageAvailability : availability }
361+ }
390362
391- try {
392- const wantOrg = intent === 'org' || intent === 'both'
393- const wantUser = intent === 'user' || intent === 'both'
394-
395- const promises : Promise < void > [ ] = [ ]
396-
397- if ( wantOrg && existenceCache . value [ `org:${ lowerName } ` ] === undefined ) {
398- promises . push (
399- checkOrgNpm ( name )
400- . then ( exists => {
401- existenceCache . value = { ...existenceCache . value , [ `org:${ lowerName } ` ] : exists }
402- } )
403- . catch ( ( ) => {
404- existenceCache . value = { ...existenceCache . value , [ `org:${ lowerName } ` ] : false }
405- } ) ,
406- )
407- }
363+ suggestionsLoading . value = true
364+ const result : SearchSuggestion [ ] = [ ]
365+ const lowerName = name . toLowerCase ( )
408366
409- if ( wantUser && existenceCache . value [ `user:${ lowerName } ` ] === undefined ) {
410- promises . push (
411- checkUserNpm ( name )
412- . then ( exists => {
413- existenceCache . value = { ...existenceCache . value , [ `user:${ lowerName } ` ] : exists }
414- } )
415- . catch ( ( ) => {
416- existenceCache . value = { ...existenceCache . value , [ `user:${ lowerName } ` ] : false }
417- } ) ,
418- )
419- }
367+ try {
368+ const wantOrg = intent === 'org' || intent === 'both'
369+ const wantUser = intent === 'user' || intent === 'both'
420370
421- if ( promises . length > 0 ) {
422- await Promise . all ( promises )
423- }
371+ const promises : Promise < void > [ ] = [ ]
424372
425- if ( requestId !== suggestionRequestId ) return
373+ if ( wantOrg && existenceCache . value [ `org:${ lowerName } ` ] === undefined ) {
374+ promises . push (
375+ checkOrgNpm ( name )
376+ . then ( exists => {
377+ existenceCache . value = { ...existenceCache . value , [ `org:${ lowerName } ` ] : exists }
378+ } )
379+ . catch ( ( ) => {
380+ existenceCache . value = { ...existenceCache . value , [ `org:${ lowerName } ` ] : false }
381+ } ) ,
382+ )
383+ }
426384
427- const isOrg = wantOrg && existenceCache . value [ `org:${ lowerName } ` ]
428- const isUser = wantUser && existenceCache . value [ `user:${ lowerName } ` ]
385+ if ( wantUser && existenceCache . value [ `user:${ lowerName } ` ] === undefined ) {
386+ promises . push (
387+ checkUserNpm ( name )
388+ . then ( exists => {
389+ existenceCache . value = { ...existenceCache . value , [ `user:${ lowerName } ` ] : exists }
390+ } )
391+ . catch ( ( ) => {
392+ existenceCache . value = { ...existenceCache . value , [ `user:${ lowerName } ` ] : false }
393+ } ) ,
394+ )
395+ }
429396
430- if ( isOrg ) {
431- result . push ( { type : 'org' , name, exists : true } )
432- }
433- if ( isUser && ! isOrg ) {
434- result . push ( { type : 'user' , name, exists : true } )
435- }
436- } finally {
437- if ( requestId === suggestionRequestId ) {
438- suggestionsLoading . value = false
439- }
397+ if ( promises . length > 0 ) {
398+ await Promise . all ( promises )
440399 }
441400
442- if ( requestId === suggestionRequestId ) {
443- suggestions . value = result
401+ if ( requestId !== suggestionRequestId . value )
402+ return { suggestions : [ ] , packageAvailability : availability }
403+
404+ const isOrg = wantOrg && existenceCache . value [ `org:${ lowerName } ` ]
405+ const isUser = wantUser && existenceCache . value [ `user:${ lowerName } ` ]
406+
407+ if ( isOrg ) {
408+ result . push ( { type : 'org' , name, exists : true } )
409+ }
410+ if ( isUser && ! isOrg ) {
411+ result . push ( { type : 'user' , name, exists : true } )
412+ }
413+ } finally {
414+ if ( requestId === suggestionRequestId . value ) {
415+ suggestionsLoading . value = false
444416 }
445417 }
446418
447- watch (
448- ( ) => toValue ( query ) ,
449- q => {
450- if ( searchProvider . value !== 'algolia' ) {
451- validateSuggestionsNpm ( q )
452- }
453- } ,
454- { immediate : true } ,
455- )
419+ if ( requestId === suggestionRequestId . value ) {
420+ suggestions . value = result
421+ return { suggestions : result , packageAvailability : availability }
422+ }
423+
424+ return { suggestions : [ ] , packageAvailability : availability }
425+ }
426+
427+ const npmSuggestions = useLazyAsyncData (
428+ ( ) => `npm-suggestions:${ searchProvider . value } :${ toValue ( query ) } ` ,
429+ async ( ) => {
430+ const q = toValue ( query ) . trim ( )
431+ if ( searchProvider . value === 'algolia' || ! q )
432+ return { suggestions : [ ] , packageAvailability : null }
433+ const { intent, name } = parseSuggestionIntent ( q )
434+ if ( ! intent || ! name ) return { suggestions : [ ] , packageAvailability : null }
435+ return validateSuggestionsNpm ( q )
436+ } ,
437+ { default : ( ) => ( { suggestions : [ ] , packageAvailability : null } ) } ,
438+ )
456439
457- watch ( searchProvider , ( ) => {
458- if ( searchProvider . value !== 'algolia' ) {
459- validateSuggestionsNpm ( toValue ( query ) )
440+ watch (
441+ [ ( ) => asyncData . data . value . suggestions , ( ) => npmSuggestions . data . value . suggestions ] ,
442+ ( [ algoliaSuggestions , npmSuggestions ] ) => {
443+ if ( algoliaSuggestions . length || npmSuggestions . length ) {
444+ suggestions . value = algoliaSuggestions . length ? algoliaSuggestions : npmSuggestions
460445 }
446+ } ,
447+ { immediate : true } ,
448+ )
449+
450+ watch (
451+ [
452+ ( ) => asyncData . data . value ?. packageAvailability ,
453+ ( ) => npmSuggestions . data . value . packageAvailability ,
454+ ] ,
455+ ( [ algoliaPackageAvailability , npmPackageAvailability ] ) => {
456+ if ( algoliaPackageAvailability || npmPackageAvailability ) {
457+ packageAvailability . value = algoliaPackageAvailability || npmPackageAvailability
458+ }
459+ } ,
460+ { immediate : true } ,
461+ )
462+
463+ if ( import . meta. client && asyncData . data . value ?. searchResponse . isStale ) {
464+ onMounted ( ( ) => {
465+ asyncData . refresh ( )
461466 } )
462467 }
463468
0 commit comments