🔍 Search Result Models
Structures in pkg/domain describing Packagist search results. They correspond to https://packagist.org/search.json API, deserialized by ComposerClient.SearchPackages / SearchPackagesByTags / SearchPackagesByType.
Type Overview
| Type | Role |
|---|---|
SearchResponse | Search response top-level (result list + total count + pagination links) |
SearchResult | Single search result |
🔎 SearchResponse
Top-level structure for search responses.
type SearchResponse struct {
Results []SearchResult `json:"results"`
Total int `json:"total"`
Next string `json:"next,omitempty"`
}| Field | Type | Description |
|---|---|---|
Results | []SearchResult | Current page search result list |
Total | int | Total matching result count (across all pages) |
Next | string | Next page URL, empty string when no next page |
Pagination approach
Next field is the complete next page URL returned by Packagist. SDK internally encapsulates page/perPage parameters, recommend using SearchPackages(query, perPage, page) for pagination instead of manually parsing Next.
📄 SearchResult
Single search result, describing a matched package.
type SearchResult struct {
Name string `json:"name"`
Description string `json:"description"`
URL string `json:"url"`
Repository string `json:"repository"`
Downloads int `json:"downloads"`
Favers int `json:"favers"`
}| Field | Type | Description |
|---|---|---|
Name | string | Package name (e.g., monolog/monolog) |
Description | string | Package description |
URL | string | Package page URL on Packagist |
Repository | string | Source code repository URL |
Downloads | int | Download count |
Favers | int | Favorite count |
Note naming conflict
pkg/composer package also has a struct named SearchResult (for parsing local composer search JSON output) with different fields. Both belong to different packages, distinguish by import: domain.SearchResponse (API search) vs composer.SearchResult (local CLI search).
🚀 Example: Search and Paginate
package main
import (
"fmt"
"log"
"time"
"github.com/scagogogo/composer-skills/pkg/client"
)
func main() {
c := client.NewComposerClient(30 * time.Second)
const perPage = 15
for page := 1; ; page++ {
resp, err := c.SearchPackages("http", perPage, page)
if err != nil {
log.Fatal(err)
}
for _, r := range resp.Results {
fmt.Printf("%-40s downloads:%-8d ★:%d\n", r.Name, r.Downloads, r.Favers)
}
if resp.Next == "" || len(resp.Results) == 0 {
break
}
}
}🔀 Search by Tags / Type
// Search by tags
byTags, _ := c.SearchPackagesByTags([]string{"logging", "psr-3"}, 15, 1)
// Search by type (with query word)
byType, _ := c.SearchPackagesByType("log", "library", 15, 1)All three search methods return *domain.SearchResponse with identical structure.
📚 Related Documentation
- 🔙 Back to Domain Overview
- 📦 Get package details after getting name → package.md
- 📊 Popular package list → create-package.md