@@ -39,6 +39,7 @@ import {
3939 CommandSeparator ,
4040} from "@/components/ui/command" ;
4141import { apiV1 , apiV1Path } from "@/lib/api-path" ;
42+ import { fetchSafeInternalApi } from "@/lib/security/http-client" ;
4243import { cn } from "@/lib/utils" ;
4344import { toast } from "sonner" ;
4445
@@ -427,7 +428,7 @@ export default function GlobalCommand() {
427428 abortRef . current = ac ;
428429 setLoading ( ! cached ) ;
429430 const searchPath = apiV1 ( "/search" ) ;
430- fetch ( `${ searchPath } ?q=${ encodeURIComponent ( query ) } ` , {
431+ fetchSafeInternalApi ( `${ searchPath } ?q=${ encodeURIComponent ( query ) } ` , {
431432 signal : ac . signal ,
432433 } )
433434 . then ( async ( r ) => {
@@ -496,29 +497,36 @@ export default function GlobalCommand() {
496497
497498 const toggleFavorite = async ( item : SearchItem ) => {
498499 const nextValue = ! getIsFavorite ( item ) ;
500+ const updateFavorite = async ( ) => {
501+ if ( item . type === "file" ) {
502+ if ( ! item . slug ) throw new Error ( "Missing file slug" ) ;
503+ return fetchSafeInternalApi (
504+ apiV1Path ( "/files" , item . slug , "favorite" ) ,
505+ {
506+ method : "PATCH" ,
507+ } ,
508+ ) ;
509+ }
510+
511+ const safeType = item . type
512+ . trim ( )
513+ . toLowerCase ( )
514+ . replace ( / [ ^ a - z 0 - 9 - ] / g, "" ) ;
515+ if ( ! safeType ) throw new Error ( "Unsupported item type" ) ;
516+
517+ return fetchSafeInternalApi ( apiV1Path ( `/${ safeType } s` , item . id ) , {
518+ method : "PATCH" ,
519+ headers : { "Content-Type" : "application/json" } ,
520+ body : JSON . stringify ( { isFavorite : nextValue } ) ,
521+ } ) ;
522+ } ;
523+
499524 const key = `${ item . type } :${ item . id } ` ;
500525 setActionLoading ( ( prev ) => ( { ...prev , [ `fav:${ key } ` ] : true } ) ) ;
501526 setFavoriteOverrides ( ( prev ) => ( { ...prev , [ key ] : nextValue } ) ) ;
502527 try {
503- if ( item . type === "file" ) {
504- if ( ! item . slug ) throw new Error ( "Missing file slug" ) ;
505- const res = await fetch ( apiV1Path ( "/files" , item . slug , "favorite" ) , {
506- method : "PATCH" ,
507- } ) ;
508- if ( ! res . ok ) throw new Error ( "Failed to update favorite" ) ;
509- } else {
510- const safeType = item . type
511- . trim ( )
512- . toLowerCase ( )
513- . replace ( / [ ^ a - z 0 - 9 - ] / g, "" ) ;
514- if ( ! safeType ) throw new Error ( "Unsupported item type" ) ;
515- const res = await fetch ( apiV1Path ( `/${ safeType } s` , item . id ) , {
516- method : "PATCH" ,
517- headers : { "Content-Type" : "application/json" } ,
518- body : JSON . stringify ( { isFavorite : nextValue } ) ,
519- } ) ;
520- if ( ! res . ok ) throw new Error ( "Failed to update favorite" ) ;
521- }
528+ const res = await updateFavorite ( ) ;
529+ if ( ! res . ok ) throw new Error ( "Failed to update favorite" ) ;
522530 } catch {
523531 setFavoriteOverrides ( ( prev ) => ( { ...prev , [ key ] : ! nextValue } ) ) ;
524532 toast . error ( "Failed to update favorite" ) ;
@@ -557,9 +565,21 @@ export default function GlobalCommand() {
557565 const toggleTypeFilter = ( type : string ) => {
558566 if ( typeTokens . length ) {
559567 const token = `type:${ type } ` ;
560- const regex = new RegExp ( `\\btype:${ type } s?\\b` , "i" ) ;
561- const next = regex . test ( q )
562- ? q . replace ( regex , " " ) . replace ( / \s + / g, " " ) . trim ( )
568+ const lowerToken = token . toLowerCase ( ) ;
569+ const lowerPluralToken = `${ token } s` . toLowerCase ( ) ;
570+ const words = q . split ( / \s + / ) . filter ( Boolean ) ;
571+ const hasToken = words . some ( ( word ) => {
572+ const lowerWord = word . toLowerCase ( ) ;
573+ return lowerWord === lowerToken || lowerWord === lowerPluralToken ;
574+ } ) ;
575+ const next = hasToken
576+ ? words
577+ . filter ( ( word ) => {
578+ const lowerWord = word . toLowerCase ( ) ;
579+ return lowerWord !== lowerToken && lowerWord !== lowerPluralToken ;
580+ } )
581+ . join ( " " )
582+ . trim ( )
563583 : `${ q } ${ token } ` . trim ( ) ;
564584 setQ ( next ) ;
565585 return ;
0 commit comments