Skip to content

🔌 ComposerClient

pkg/client.ComposerClient is the high-level facade for the Packagist API SDK. It wraps Packagist's public HTTP/JSON endpoints into 20 type-safe Go methods, returning values as strongly-typed structures from pkg/domain. Callers don't need to handle HTTP requests, status code checks, or JSON deserialization themselves.

Pure Go, No PHP Required

ComposerClient only depends on Go standard library net/http, does not call local composer binary, and does not require PHP runtime. It can be used independently from the Composer CLI SDK.

When to Use

  • 🌐 Your service needs to query package metadata, download statistics, or security advisories on Packagist from Go.
  • 🛠️ CI/CD pipeline Go scripts check dependency vulnerabilities or download counts, without installing PHP just for one HTTP call.
  • 📊 Need to persist Packagist data for long-term trend analysis; ComposerClient gives you strongly-typed structures ready for database storage.
  • 🔌 Need to point to a self-hosted mirror / Satis instance: use WithBaseURL / WithRepoURL to override default addresses.

Creating a Client

NewComposerClient

go
func NewComposerClient(timeout time.Duration, options ...ComposerClientOption) *ComposerClient
ParameterTypeDescription
timeouttime.DurationHTTP client overall timeout, passed to http.Client.Timeout
options...ComposerClientOptionOptional configuration functions to override default base URL, repo URL, API credentials as needed

Default Values:

FieldDefault ValueMeaning
baseURLhttps://packagist.orgBusiness API endpoint (package info, search, statistics, listing, management)
repoURLhttps://repo.packagist.orgRepository metadata endpoint (V2 metadata p2/..., dev versions)
username / apiTokenEmptyOnly needed for write operations, see WithAPICredentials

Example

go
package main

import (
    "fmt"
    "log"
    "time"

    "github.com/scagogogo/composer-skills/pkg/client"
)

func main() {
    // Minimal: 30 second timeout, anonymous access to official Packagist
    c := client.NewComposerClient(30 * time.Second)

    stats, err := c.GetStatistics()
    if err != nil {
        log.Fatalf("Failed to get statistics: %v", err)
    }
    fmt.Printf("Packagist has %d packages\n", stats.Totals.Packages)
}

Configuration Options

All options are ComposerClientOption functions, passed to NewComposerClient as needed.

WithBaseURL

go
func WithBaseURL(baseURL string) ComposerClientOption
ParameterTypeDescription
baseURLstringBusiness API base URL, overrides default https://packagist.org

After overriding, GetPackage, GetStatistics, SearchPackages, ListPackages*, GetSecurityAdvisories*, CreatePackage and other methods will all prepend this prefix. Use when pointing to a self-hosted Packagist mirror or private Packagist instance.

go
c := client.NewComposerClient(
    30*time.Second,
    client.WithBaseURL("https://packagist.mycompany.com"),
)

WithRepoURL

go
func WithRepoURL(repoURL string) ComposerClientOption
ParameterTypeDescription
repoURLstringRepository metadata base URL, overrides default https://repo.packagist.org

Only affects GetPackageWithV2Metadata and GetPackageDevVersions methods (they use p2/... endpoint).

go
c := client.NewComposerClient(
    30*time.Second,
    client.WithRepoURL("https://repo.packagist.mycompany.com"),
)

WithAPICredentials

go
func WithAPICredentials(username, apiToken string) ComposerClientOption
ParameterTypeDescription
usernamestringPackagist account username
apiTokenstringPackagist personal API token (generated on packagist.org profile page)

Credential Security

username and apiToken will be appended to request URL as query parameters (Packagist API design). Do not print complete request URLs in insecure logs. We recommend reading from environment variables or secret management services, not hardcoding in source code.

Only three write operations require credentials, calling without configuration will return an error directly:

go
c := client.NewComposerClient(
    30*time.Second,
    client.WithAPICredentials(
        os.Getenv("PACKAGIST_USERNAME"),
        os.Getenv("PACKAGIST_API_TOKEN"),
    ),
)

Complete Method List

The table below lists all 20 methods of ComposerClient. Detailed signatures, parameters, and examples are in corresponding sub-documents.

MethodSignature SummaryReturn TypeSub-document
📦 GetPackage(packageName string)(*domain.ComposerPackageInfo, error)package-info
📦 GetPackageWithV2Metadata(packageName string)([]byte, error)package-info
📦 GetPackageDevVersions(packageName string)([]byte, error)package-info
📦 GetPackageStats(packageName string)(*domain.PackageStatsResponse, error)package-info
📦 GetPackageChanges(ctx context.Context, since int64)(*domain.ChangeTrackingResponse, error)package-info
🔍 SearchPackages(query string, perPage, page int)(*domain.SearchResponse, error)search
🔍 SearchPackagesByTags(tags []string, perPage, page int)(*domain.SearchResponse, error)search
🔍 SearchPackagesByType(query, packageType string, perPage, page int)(*domain.SearchResponse, error)search
📊 GetStatistics()(*domain.StatisticsResponse, error)statistics
🔒 GetSecurityAdvisories()(*domain.AdvisoriesResponse, error)advisories
🔒 GetSecurityAdvisoriesForPackages(packageNames []string)(*domain.AdvisoriesResponse, error)advisories
🔒 GetSecurityAdvisoriesSince(updatedSince time.Time)(*domain.AdvisoriesResponse, error)advisories
📋 ListPackages()(*domain.PackageListResponse, error)listing
📋 ListPackagesByVendor(vendor string)(*domain.PackageListResponse, error)listing
📋 ListPackagesByType(packageType string)(*domain.PackageListResponse, error)listing
📋 ListPackagesWithData(fields []string)(*domain.PackageListWithDataResponse, error)listing
📋 ListPopularPackages(perPage int)(*domain.PopularPackagesResponse, error)listing
🛠️ CreatePackage(ctx, *domain.PackageCreateRequest)(*domain.PackageCreateResponse, error)management
🛠️ EditPackage(ctx, packageName, *domain.PackageEditRequest)(*domain.PackageEditResponse, error)management
🛠️ UpdatePackage(ctx, *domain.PackageUpdateRequest)(*domain.PackageUpdateResponse, error)management

Advanced Topics

Timeout Settings

The first parameter timeout of NewComposerClient is directly assigned to http.Client.Timeout, covering all phases (connection, TLS handshake, reading body). Production environments should set 30s-60s; when downloading large indexes (ListPackagesWithData returns large volume), consider increasing timeout, or use lower-level Repository layer DownloadIndexToFile to save to disk for streaming processing.

go
c := client.NewComposerClient(60 * time.Second)

Note

ComposerClient does not support custom http.Transport (if you need custom retry, connection pool, TLS configuration, use lower-level repository.Repository, which supports Proxy and other settings via go-requests).

Combining Multiple Options

go
c := client.NewComposerClient(
    45*time.Second,
    client.WithBaseURL("https://packagist.mycompany.com"),
    client.WithRepoURL("https://repo.packagist.mycompany.com"),
    client.WithAPICredentials(user, token),
)

Released under the MIT License