🛠️ Create / Edit / List Models
Structures in pkg/domain used for package management (create, edit, update) and package list/popular package queries. These types serve as both API request bodies and response bodies, corresponding to Packagist's https://packagist.org/api/... write endpoints and https://packagist.org/packages/list.json read endpoint.
Type Overview
| Type | Role | Requires Credentials |
|---|---|---|
PackageCreateRequest / PackageCreateResponse | Create package | ✅ Required |
PackageEditRequest / PackageEditResponse | Edit package | ✅ Required |
PackageUpdateRequest / PackageUpdateResponse | Update package | ✅ Required |
PackageListResponse | Package name list | ❌ Public |
PackageListWithDataResponse / PackageData | Package list with additional data | ❌ Public |
PopularPackagesResponse / PopularPackage | Popular package list | ❌ Public |
Write operations require API credentials
Create/edit/update packages are write operations that require credentials via client.WithAPICredentials(username, apiToken), otherwise Packagist will reject them.
✏️ Create Package
PackageCreateRequest
type PackageCreateRequest struct {
Repository string `json:"repository"`
}| Field | Type | Description |
|---|---|---|
Repository | string | Repository URL of the package to submit (e.g., https://github.com/symfony/console) |
PackageCreateResponse
type PackageCreateResponse struct {
Status string `json:"status"`
}| Field | Type | Description |
|---|---|---|
Status | string | Operation status (e.g., success) |
📝 Edit Package
PackageEditRequest
type PackageEditRequest struct {
Repository string `json:"repository"`
}| Field | Type | Description |
|---|---|---|
Repository | string | New repository URL to replace the package's original repository address |
PackageEditResponse
type PackageEditResponse struct {
Status string `json:"status"`
}| Field | Type | Description |
|---|---|---|
Status | string | Operation status |
Create vs Edit
- Create (
CreatePackage): Register a new package to Packagist, only need to pass repository URL. - Edit (
EditPackage): Modify existing package's repository address, need to specify both package name (in method parameter) and new repository URL. - Update (
UpdatePackage): Trigger Packagist to re-fetch metadata for a package, usually without changing repository address.
🔄 Update Package
PackageUpdateRequest
type PackageUpdateRequest struct {
Repository string `json:"repository"`
}| Field | Type | Description |
|---|---|---|
Repository | string | Package name or repository identifier to trigger update |
PackageUpdateResponse
type PackageUpdateResponse struct {
Status string `json:"status"`
Jobs []string `json:"jobs,omitempty"`
}| Field | Type | Description |
|---|---|---|
Status | string | Operation status |
Jobs | []string | List of triggered background job IDs (can be used to poll update progress) |
📋 Package Name List
PackageListResponse
Corresponds to https://packagist.org/packages/list.json, returns all package names in Packagist.
type PackageListResponse struct {
PackageNames []string `json:"packageNames"`
}| Field | Type | Description |
|---|---|---|
PackageNames | []string | Package name list |
📋 Package List with Additional Data
PackageListWithDataResponse
Corresponds to https://packagist.org/packages/list.json?fields[]=repository&fields[]=type, returns mapping from package names to additional data.
type PackageListWithDataResponse struct {
Packages map[string]PackageData `json:"package"`
}| Field | Type | Description |
|---|---|---|
Packages | map[string]PackageData | Package info mapping, key is package name, value is additional data |
PackageData
type PackageData struct {
Type string `json:"type,omitempty"`
Repository string `json:"repository,omitempty"`
Abandoned interface{} `json:"abandoned,omitempty"`
}| Field | Type | Description |
|---|---|---|
Type | string | Package type (e.g., library) |
Repository | string | Repository URL |
Abandoned | interface{} | Whether abandoned: can be bool (false/true) or string (recommended replacement package name) |
Abandoned is a union type
Abandoned in JSON can be either boolean or string:
false/true: indicates not abandoned / abandoned (no replacement package)"vendor/replacement": abandoned, recommends migrating to this replacement package
Therefore Go uses interface{} to receive it. Type assertion is needed when using:
switch v := data.Abandoned.(type) {
case bool:
if v { fmt.Println("Abandoned, no replacement package") }
case string:
fmt.Printf("Abandoned, replacement package: %s\n", v)
}⭐ Popular Packages
PopularPackagesResponse
Corresponds to https://packagist.org/explore/popular.json, returns popular package list.
type PopularPackagesResponse struct {
Packages []PopularPackage `json:"packages"`
Total int `json:"total"`
Next string `json:"next,omitempty"`
}| Field | Type | Description |
|---|---|---|
Packages | []PopularPackage | Popular package info list |
Total | int | Total popular package count |
Next | string | Next page URL, empty if none |
PopularPackage
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 |
|---|---|---|
Name | string | Package name |
Description | string | Package description |
URL | string | Package page URL |
Downloads | int | Download count |
Favers | int | Favorite count |
Difference from SearchResult
PopularPackage fields are nearly identical to domain.SearchResult, but semantically different: former comes from "popular packages" list (sorted by favorites/downloads), latter from keyword search. Both are defined separately to allow independent evolution.
🚀 Examples
Create Package (requires credentials)
package main
import (
"context"
"fmt"
"log"
"time"
"github.com/scagogogo/composer-skills/pkg/client"
"github.com/scagogogo/composer-skills/pkg/domain"
)
func main() {
c := client.NewComposerClient(30*time.Second,
client.WithAPICredentials("your-username", "your-api-token"),
)
resp, err := c.CreatePackage(context.Background(), &domain.PackageCreateRequest{
Repository: "https://github.com/your-org/your-package",
})
if err != nil {
log.Fatal(err)
}
fmt.Printf("Create result: %s\n", resp.Status)
}List Packages with Additional Data
list, _ := c.ListPackagesWithData([]string{"repository", "type"})
for name, data := range list.Packages {
fmt.Printf("%s type=%s repo=%s\n", name, data.Type, data.Repository)
}Get Popular Packages
popular, _ := c.ListPopularPackages(20)
for _, p := range popular.Packages {
fmt.Printf("%-30s ★%-6d downloads:%d\n", p.Name, p.Favers, p.Downloads)
}📚 Related Documentation
- 🔙 Back to Domain Overview
- 📦 Package detail fields → package.md
- 📊 Download statistics → statistics.md