Skip to content

📋 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., all composer-plugin).
  • 🔄 Mirror sync: Use ListPackagesWithData to get package names + repository URLs + types in one call.
  • 📈 Use ListPopularPackages to generate popular package rankings.

Data Models

PackageListResponse

pkg/domain/package_list.go, corresponds to /packages/list.json (without fields).

go
type PackageListResponse struct {
    PackageNames []string `json:"packageNames"`
}
FieldTypeDescription
PackageNames[]stringPackage name list (vendor/package)

PackageListWithDataResponse / PackageData

Corresponds to /packages/list.json?fields[]=..., with additional fields.

go
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"`
}
FieldTypeDescription
Packagesmap[string]PackageDataKey is package name, value is additional data
PackageData.TypestringPackage type (need to request type in fields)
PackageData.RepositorystringRepository URL (need to request repository)
PackageData.Abandonedinterface{}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.

go
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"`
}
FieldTypeDescription
Packages[]PopularPackageCurrent page popular package list
TotalintTotal popular packages count
NextstringNext page URL (empty if none)
PopularPackage.NamestringPackage name
PopularPackage.DescriptionstringDescription
PopularPackage.URLstringPackagist page URL
PopularPackage.DownloadsintDownload count
PopularPackage.FaversintFavorites count

ListPackages

📋 Get all package names list. Corresponds to GET https://packagist.org/packages/list.json.

Signature

go
func (c *ComposerClient) ListPackages() (*domain.PackageListResponse, error)

Parameters

None.

Return Values

ValueTypeDescription
Result*domain.PackageListResponseContains full PackageNames
ErrorerrorReturned on HTTP failure, non-200, or JSON parsing failure

Example

go
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

go
func (c *ComposerClient) ListPackagesByVendor(vendor string) (*domain.PackageListResponse, error)

Parameters

ParameterTypeDescription
vendorstringVendor name, e.g., symfony, laravel

Return Values

ValueTypeDescription
Result*domain.PackageListResponsePackage names list under that vendor
ErrorerrorReturned on HTTP failure, non-200, or JSON parsing failure

Example

go
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

go
func (c *ComposerClient) ListPackagesByType(packageType string) (*domain.PackageListResponse, error)

Parameters

ParameterTypeDescription
packageTypestringPackage type, e.g., library, composer-plugin, project, metapackage

Return Values

ValueTypeDescription
Result*domain.PackageListResponsePackage names list of that type
ErrorerrorReturned on HTTP failure, non-200, or JSON parsing failure

Example

go
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

go
func (c *ComposerClient) ListPackagesWithData(fields []string) (*domain.PackageListWithDataResponse, error)

Parameters

ParameterTypeDescription
fields[]stringAdditional field names to return, each sent as a fields[] query parameter

Optional field values (refer to Packagist documentation):

FieldDescription
repositoryRepository URL
typePackage type
abandonedAbandoned marker (boolean or recommended replacement package name)

Return Values

ValueTypeDescription
Result*domain.PackageListWithDataResponsePackage name → additional data mapping
ErrorerrorReturned on HTTP failure, non-200, or JSON parsing failure

Example

go
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

go
func (c *ComposerClient) ListPopularPackages(perPage int) (*domain.PopularPackagesResponse, error)

Parameters

ParameterTypeDescription
perPageintItems per page, directly appended as per_page query parameter

Return Values

ValueTypeDescription
Result*domain.PopularPackagesResponseContains Packages, Total, Next
ErrorerrorReturned on HTTP failure, non-200, or JSON parsing failure

Example

go
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

MethodReturnDimensionUse Case
ListPackagesPackage name arrayFullFull traversal
ListPackagesByVendorPackage name arrayBy vendorVendor-level analysis
ListPackagesByTypePackage name arrayBy typeType-level analysis
ListPackagesWithDataPackage name → additional fieldsFull + fieldsMirror sync (with repository URL)
ListPopularPackagesPopular package detailsRankingPopular package display

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.

Released under the MIT License