1- import gleam/bool
21import gleam/dict
32import gleam/dynamic/decode . { type Decoder }
43import gleam/float
@@ -14,6 +13,7 @@ import gleam/time/calendar
1413import gleam/time/timestamp . { type Timestamp }
1514import packages/error . { type Error }
1615import packages/override
16+ import packages/text_search
1717import storail . { type Collection }
1818
1919pub opaque type Database {
@@ -370,72 +370,63 @@ pub fn list_packages(database: Database) -> Result(List(String), Error) {
370370 }
371371}
372372
373- type Groups {
374- Groups (
375- exact : List ( Package ) ,
376- regular : List ( Package ) ,
377- v0 : List ( Package ) ,
378- old : List ( Package ) ,
379- )
380- }
381-
382- pub fn ranked_package_summaries (
383- database : Database ,
384- packages : List ( String ) ,
373+ pub fn search_packages (
374+ db : Database ,
375+ search : text_search . TextSearchIndex ,
385376 search_term : String ,
386377) -> Result ( List ( Package ) , Error ) {
387- let gleam_v1 =
388- timestamp . from_calendar (
389- calendar . Date ( 2024 , calendar . March , 4 ) ,
390- calendar . TimeOfDay ( 0 , 0 , 0 , 0 ) ,
391- calendar . utc_offset ,
392- )
393-
394- use packages <- result . map ( {
395- use name <- list . try_map ( packages )
396- get_package ( database , name )
397- } )
378+ let bool = fn ( b ) {
379+ case b {
380+ True -> 1
381+ False -> 0
382+ }
383+ }
384+ use found <- result . try ( text_search . lookup ( search , search_term ) )
385+ use packages <- result . map (
386+ list . try_map ( found , fn ( found ) {
387+ use package <- result . map ( get_package ( db , found . name ) )
388+
389+ let exact_package_name_match = bool ( search_term == package . name )
390+ let is_not_v0 = bool ( ! string . starts_with ( package . latest_version , "0." ) )
391+ let is_core_package = bool ( override . is_core_package ( package . name ) )
392+ let updated_at =
393+ float . round ( timestamp . to_unix_seconds ( package . updated_in_hex_at ) )
394+
395+ // This is the value we use to determine what order packages should be
396+ // shown by. Later list values only take effect if the earlier ones are
397+ // equal.
398+ let ordering_key = [
399+ exact_package_name_match ,
400+ is_not_v0 ,
401+ found . match_count ,
402+ is_core_package ,
403+ package . downloads_recent ,
404+ updated_at ,
405+ ]
406+ # ( ordering_key , package )
407+ } ) ,
408+ )
398409
399- let groups = Groups ( [ ] , [ ] , [ ] , [ ] )
400-
401- let groups =
402- list . fold ( packages , groups , fn ( groups , package ) {
403- // The ordering of the clauses matter. Something can be both v0 and old,
404- // and which group it goes into impacts the final ordering.
405-
406- use <- bool . lazy_guard ( package . name == search_term , fn ( ) {
407- Groups ( .. groups , exact : [ package , .. groups . exact ] )
408- } )
409-
410- let is_old =
411- timestamp . compare ( package . updated_in_hex_at , gleam_v1 ) == order . Lt
412- use <- bool . lazy_guard ( is_old , fn ( ) {
413- Groups ( .. groups , old : [ package , .. groups . old ] )
414- } )
415-
416- let is_zero_version = string . starts_with ( package . latest_version , "0." )
417- use <- bool . lazy_guard ( is_zero_version , fn ( ) {
418- Groups ( .. groups , v0 : [ package , .. groups . v0 ] )
419- } )
420-
421- Groups ( .. groups , regular : [ package , .. groups . regular ] )
422- } )
423-
424- let Groups ( exact : , regular : , v0 : , old : ) = groups
425- // This list is ordered backwards, so the later in the list the higher it
426- // will be shown in the UI.
427- [
428- // Packages published before Gleam v1.0.0 are likely outdated.
429- old ,
430- // v0 versions are discouraged, so they are shown lower.
431- v0 ,
432- // Regular versions are not prioritised in any particular way.
433- regular ,
434- // Exact matches for the search term come first.
435- exact ,
436- ]
437- |> list . flatten
438- |> list . reverse
410+ packages
411+ |> list . sort ( fn ( a , b ) { list_compare ( b . 0 , a . 0 , int . compare ) } )
412+ |> list . map ( fn ( pair ) { pair . 1 } )
413+ }
414+
415+ fn list_compare (
416+ a : List ( t) ,
417+ b : List ( t) ,
418+ compare : fn ( t, t) -> order . Order ,
419+ ) -> order . Order {
420+ case a , b {
421+ [ ] , [ ] -> order . Eq
422+ [ ] , _ -> order . Lt
423+ _ , [ ] -> order . Gt
424+ [ a1 , .. a ] , [ b1 , .. b ] ->
425+ case compare ( a1 , b1 ) {
426+ order . Eq -> list_compare ( a , b , compare )
427+ order . Gt as order | order . Lt as order -> order
428+ }
429+ }
439430}
440431
441432pub fn try_fold_packages (
@@ -564,3 +555,11 @@ fn date_string(timestamp: Timestamp) -> String {
564555 |> timestamp . to_rfc3339 ( calendar . utc_offset )
565556 |> string . slice ( 0 , 10 )
566557}
558+
559+ pub fn packages_most_recent_first ( db : Database ) -> Result ( List ( Package ) , Error ) {
560+ use packages <- result . try ( list_packages ( db ) )
561+ use packages <- result . map ( list . try_map ( packages , get_package ( db , _) ) )
562+ list . sort ( packages , fn ( a , b ) {
563+ timestamp . compare ( b . updated_in_hex_at , a . updated_in_hex_at )
564+ } )
565+ }
0 commit comments