📋 Package Listing
Batch fetch package name lists from Packagist by vendor, type, or additional fields, and get popular package rankings. Unlike Search, listing methods return package name sets (no search scoring), suitable for full traversal, mirror sync, ecosystem statistics.
When to Use
- 📋 Full traversal of a vendor (e.g., all packages under
symfony/*) for dependency analysis. - 🏷️ Fetch all packages of a certain
type(e.g., allcomposer-plugin). - 🔄 Mirror sync: Use
ListPackagesWithDatato get package names + repository URLs + types in one call. - 📈 Use
ListPopularPackagesto generate popular package rankings.
Data Models
PackageListResponse
pkg/domain/package_list.go, corresponds to /packages/list.json (without fields).
type PackageListResponse struct {
PackageNames []string `json:"packageNames"`
}| Field | Type | Description |
|---|---|---|
PackageNames | []string | Package name list (vendor/package) |
PackageListWithDataResponse / PackageData
Corresponds to /packages/list.json?fields[]=..., with additional fields.
type PackageListWithDataResponse struct {
Packages map[string]PackageData `json:"package"`
}
type PackageData struct {
Type string `json:"type,omitempty"`
Repository string `json:"repository,omitempty"`
Abandoned interface{} `json:"abandoned,omitempty"`
}| Field | Type | Description |
|---|---|---|
Packages | map[string]PackageData | Key is package name, value is additional data |
PackageData.Type | string | Package type (need to request type in fields) |
PackageData.Repository | string | Repository URL (need to request repository) |
PackageData.Abandoned | interface{} | Abandoned marker: false/true, or string (recommended replacement package name, need to request abandoned) |
Abandoned Field Type
Abandoned uses interface{} because Packagist return value can be boolean (false/true) or string (recommended replacement package name). Type assertion is needed when using.
PopularPackagesResponse / PopularPackage
pkg/domain/popular_packages.go, corresponds to /explore/popular.json.
type PopularPackagesResponse struct {
Packages []PopularPackage `json:"packages"`
Total int `json:"total"`
Next string `json:"next,omitempty"`
}
type PopularPackage struct {
Name string `json:"name"`
Description string `json:"description"`
URL string `json:"url"`
Downloads int `json:"downloads"`
Favers int `json:"favers"`
}| Field | Type | Description |
|---|---|---|
Packages | []PopularPackage | Current page popular package list |
Total | int | Total popular packages count |
Next | string | Next page URL (empty if none) |
PopularPackage.Name | string | Package name |
PopularPackage.Description | string | Description |
PopularPackage.URL | string | Packagist page URL |
PopularPackage.Downloads | int | Download count |
PopularPackage.Favers | int | Favorites count |
ListPackages
📋 Get all package names list. Corresponds to GET https://packagist.org/packages/list.json.
Signature
func (c *ComposerClient) ListPackages() (*domain.PackageListResponse, error)Parameters
None.
Return Values
| Value | Type | Description |
|---|---|---|
| Result | *domain.PackageListResponse | Contains full PackageNames |
| Error | error | Returned on HTTP failure, non-200, or JSON parsing failure |
Example
package main
import (
"fmt"
"log"
"time"
"github.com/scagogogo/composer-skills/pkg/client"
)
func main() {
c := client.NewComposerClient(120 * time.Second) // Full list is large, give sufficient timeout
list, err := c.ListPackages()
if err != nil {
log.Fatalf("Failed to get package list: %v", err)
}
fmt.Printf("Packagist has %d packages\n", len(list.PackageNames))
for i, name := range list.PackageNames {
if i >= 5 {
break
}
fmt.Println(" -", name)
}
}Large Response Body
/packages/list.json returns full package names (hundreds of thousands, response body tens of MB). Production environment should set timeout to 120s or more, or use lower-level Repository.List with proxy; for saving to disk use DownloadIndexToFile.
ListPackagesByVendor
📋 Get all package names under a specified vendor. Corresponds to GET https://packagist.org/packages/list.json?vendor={vendor}.
Signature
func (c *ComposerClient) ListPackagesByVendor(vendor string) (*domain.PackageListResponse, error)Parameters
| Parameter | Type | Description |
|---|---|---|
vendor | string | Vendor name, e.g., symfony, laravel |
Return Values
| Value | Type | Description |
|---|---|---|
| Result | *domain.PackageListResponse | Package names list under that vendor |
| Error | error | Returned on HTTP failure, non-200, or JSON parsing failure |
Example
list, err := c.ListPackagesByVendor("symfony")
if err != nil {
log.Fatal(err)
}
fmt.Printf("symfony/* has %d packages\n", len(list.PackageNames))
for _, name := range list.PackageNames {
fmt.Println(name)
}Vendor vs Package Name
Packagist package name format is vendor/package, vendor is the part before the slash. vendor=symfony will return all symfony/* packages.
ListPackagesByType
📋 Get all package names of a specified type. Corresponds to GET https://packagist.org/packages/list.json?type={type}.
Signature
func (c *ComposerClient) ListPackagesByType(packageType string) (*domain.PackageListResponse, error)Parameters
| Parameter | Type | Description |
|---|---|---|
packageType | string | Package type, e.g., library, composer-plugin, project, metapackage |
Return Values
| Value | Type | Description |
|---|---|---|
| Result | *domain.PackageListResponse | Package names list of that type |
| Error | error | Returned on HTTP failure, non-200, or JSON parsing failure |
Example
list, err := c.ListPackagesByType("composer-plugin")
if err != nil {
log.Fatal(err)
}
fmt.Printf("composer-plugin type has %d packages\n", len(list.PackageNames))ListPackagesWithData
📋 Get package list with additional fields (repository URL, type, abandoned marker). Corresponds to GET https://packagist.org/packages/list.json?fields[]={field}.
Signature
func (c *ComposerClient) ListPackagesWithData(fields []string) (*domain.PackageListWithDataResponse, error)Parameters
| Parameter | Type | Description |
|---|---|---|
fields | []string | Additional field names to return, each sent as a fields[] query parameter |
Optional field values (refer to Packagist documentation):
| Field | Description |
|---|---|
repository | Repository URL |
type | Package type |
abandoned | Abandoned marker (boolean or recommended replacement package name) |
Return Values
| Value | Type | Description |
|---|---|---|
| Result | *domain.PackageListWithDataResponse | Package name → additional data mapping |
| Error | error | Returned on HTTP failure, non-200, or JSON parsing failure |
Example
resp, err := c.ListPackagesWithData([]string{"repository", "type", "abandoned"})
if err != nil {
log.Fatal(err)
}
for name, data := range resp.Packages {
fmt.Printf("%s\n", name)
fmt.Printf(" Type: %s\n", data.Type)
fmt.Printf(" Repository: %s\n", data.Repository)
if data.Abandoned != nil && data.Abandoned != false {
fmt.Printf(" ⚠ Abandoned: %v\n", data.Abandoned)
}
}Field Selection
More fields requested means larger response body. Only fetch needed fields. Note: without fields, endpoint returns packageNames array (PackageListResponse); with fields, returns package mapping (PackageListWithDataResponse) — two different response structures, SDK uses different types to parse.
ListPopularPackages
📋 Get popular package rankings. Corresponds to GET https://packagist.org/explore/popular.json?per_page={n}.
Signature
func (c *ComposerClient) ListPopularPackages(perPage int) (*domain.PopularPackagesResponse, error)Parameters
| Parameter | Type | Description |
|---|---|---|
perPage | int | Items per page, directly appended as per_page query parameter |
Return Values
| Value | Type | Description |
|---|---|---|
| Result | *domain.PopularPackagesResponse | Contains Packages, Total, Next |
| Error | error | Returned on HTTP failure, non-200, or JSON parsing failure |
Example
res, err := c.ListPopularPackages(100)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Total popular packages %d, current page %d\n", res.Total, len(res.Packages))
for i, p := range res.Packages {
fmt.Printf("%2d. %s (downloads %d, favorites %d)\n", i+1, p.Name, p.Downloads, p.Favers)
}Advanced Topics
Comparison of Five Listing Methods
| Method | Return | Dimension | Use Case |
|---|---|---|---|
ListPackages | Package name array | Full | Full traversal |
ListPackagesByVendor | Package name array | By vendor | Vendor-level analysis |
ListPackagesByType | Package name array | By type | Type-level analysis |
ListPackagesWithData | Package name → additional fields | Full + fields | Mirror sync (with repository URL) |
ListPopularPackages | Popular package details | Ranking | Popular package display |
Difference from Search
Search methods use /search.json, score by relevance and paginate; listing methods use /packages/list.json, return unordered package name sets, no pagination (except ListPopularPackages). Want full data use listing, want "find most relevant by keyword" use search.
🔗 Related
- 🏗️ Full list lower-level see Repository.List and DownloadIndexToFile.
- 📦 After getting package name, query details see GetPackage.