aboutsummaryrefslogtreecommitdiffhomepage
path: root/cmd/mbf/internal/pkgserver/search.go
diff options
context:
space:
mode:
authormae <mae@maestoso.online>2026-03-04 22:50:58 -0600
committerOphestra <cat@gensokyo.uk>2026-05-02 05:05:56 +0900
commit1d5d063d6a443c9d4a1206d2743e4824411da956 (patch)
treeb32105cf3896f394be91099cfbfb67785de39385 /cmd/mbf/internal/pkgserver/search.go
parente61628a34ecccae0feb5e059a2f808977261fa0e (diff)
cmd/mbf: package status dashboard
This displays package metadata with optional status from a report.
Diffstat (limited to 'cmd/mbf/internal/pkgserver/search.go')
-rw-r--r--cmd/mbf/internal/pkgserver/search.go81
1 files changed, 81 insertions, 0 deletions
diff --git a/cmd/mbf/internal/pkgserver/search.go b/cmd/mbf/internal/pkgserver/search.go
new file mode 100644
index 00000000..5756512f
--- /dev/null
+++ b/cmd/mbf/internal/pkgserver/search.go
@@ -0,0 +1,81 @@
+package pkgserver
+
+import (
+ "cmp"
+ "maps"
+ "regexp"
+ "slices"
+ "time"
+)
+
+type searchCache map[string]searchCacheEntry
+type searchResult struct {
+ NameIndices [][]int `json:"name_matches"`
+ DescIndices [][]int `json:"desc_matches,omitempty"`
+ Score float64 `json:"score"`
+ *metadata
+}
+type searchCacheEntry struct {
+ query string
+ results []searchResult
+ expiry time.Time
+}
+
+func (index *packageIndex) performSearchQuery(limit int, i int, search string, desc bool) (int, []searchResult, error) {
+ query := search
+ if desc {
+ query += ";withDesc"
+ }
+ entry, ok := index.search[query]
+ if ok && len(entry.results) > 0 {
+ return len(entry.results), entry.results[min(i, len(entry.results)-1):min(i+limit, len(entry.results))], nil
+ }
+
+ regex, err := regexp.Compile(search)
+ if err != nil {
+ return 0, make([]searchResult, 0), err
+ }
+ res := make([]searchResult, 0)
+ for p := range maps.Values(index.names) {
+ nameIndices := regex.FindAllIndex([]byte(p.Name), -1)
+ var descIndices [][]int = nil
+ if desc {
+ descIndices = regex.FindAllIndex([]byte(p.Description), -1)
+ }
+ if nameIndices == nil && descIndices == nil {
+ continue
+ }
+ score := float64(indexsum(nameIndices)) / (float64(len(nameIndices)) + 1)
+ if desc {
+ score += float64(indexsum(descIndices)) / (float64(len(descIndices)) + 1) / 10.0
+ }
+ res = append(res, searchResult{
+ NameIndices: nameIndices,
+ DescIndices: descIndices,
+ Score: score,
+ metadata: p,
+ })
+ }
+ slices.SortFunc(res[:], func(a, b searchResult) int { return -cmp.Compare(a.Score, b.Score) })
+ expiry := time.Now().Add(1 * time.Minute)
+ entry = searchCacheEntry{
+ query: search,
+ results: res,
+ expiry: expiry,
+ }
+ index.search[query] = entry
+
+ return len(res), res[i:min(i+limit, len(entry.results))], nil
+}
+func (s *searchCache) clean() {
+ maps.DeleteFunc(*s, func(_ string, v searchCacheEntry) bool {
+ return v.expiry.Before(time.Now())
+ })
+}
+func indexsum(in [][]int) int {
+ sum := 0
+ for i := 0; i < len(in); i++ {
+ sum += in[i][1] - in[i][0]
+ }
+ return sum
+}