📦 Package Info Models
Core structures in pkg/domain describing Composer package details. They correspond to Packagist's https://repo.packagist.org/p2/<vendor>/<package>.json API response, deserialized by ComposerClient.GetPackage.
Type Overview
| Type | Role | Key Field Count |
|---|---|---|
ComposerPackageInfo | Package complete info (top-level wrapper) | 5 |
PackageInfo | Package business info body | 15 |
PackageDownloads | Download stats sub-structure | 3 |
Maintainer | Maintainer | 2 |
Version | Single version metadata | 18+ |
🗂️ ComposerPackageInfo
Package complete info, containing primary key, lowercase package name, business info, md5 fingerprint, and three timestamps. This is the direct return type of GetPackage.
type ComposerPackageInfo struct {
PackageName string `json:"package_name" bson:"package_name"`
PackageNameLowercase string `json:"package_name_lowercase" bson:"package_name_lowercase"`
Package PackageInfo `json:"package" bson:"package"`
PackageInfoMd5 string `json:"package_info_md5" bson:"package_info_md5"`
CreateTime *time.Time `json:"create_time" bson:"create_time"`
UpdateTime *time.Time `json:"update_time" bson:"update_time"`
ChangeTime *time.Time `json:"change_time" bson:"change_time"`
}| Field | Type | Description |
|---|---|---|
PackageName | string | Package name, as unique primary key (e.g., symfony/console) |
PackageNameLowercase | string | Lowercase package name, for case-insensitive queries |
Package | PackageInfo | Package detailed business info, see next section |
PackageInfoMd5 | string | Package info md5 fingerprint, used to detect content changes |
CreateTime | *time.Time | Package record creation time (pointer type, can be nil) |
UpdateTime | *time.Time | Package record update time |
ChangeTime | *time.Time | Time when package info content actually changed |
Difference between three timestamps
CreateTime: Record first入库 timeUpdateTime: Time when any field was refreshedChangeTime: Time when content actually changed (md5 differs), commonly used for incremental sync
📑 PackageInfo
Package business info body, nested in ComposerPackageInfo.Package.
type PackageInfo struct {
Name string `json:"name" bson:"name"`
Description string `json:"description" bson:"description"`
Time time.Time `json:"time" bson:"time"`
Maintainers []*Maintainer `json:"maintainers" bson:"maintainers"`
Versions map[string]*Version `json:"versions" bson:"versions"`
Type string `json:"type" bson:"type"`
Repository string `json:"repository" bson:"repository"`
GithubStars int `json:"github_stars" bson:"github_stars"`
GithubWatchers int `json:"github_watchers" bson:"github_watchers"`
GithubForks int `json:"github_forks" bson:"github_forks"`
GithubOpenIssues int `json:"github_open_issues" bson:"github_open_issues"`
Language string `json:"language" bson:"language"`
Dependents int `json:"dependents" bson:"dependents"`
Suggesters int `json:"suggesters" bson:"suggesters"
Downloads PackageDownloads `json:"downloads" bson:"downloads"`
Favers int `json:"favers" bson:"favers"`
}| Field | Type | Description |
|---|---|---|
Name | string | Package name |
Description | string | Package description |
Time | time.Time | Package creation time |
Maintainers | []*Maintainer | Maintainer list |
Versions | map[string]*Version | All versions, key is version number (e.g., v6.0.0) |
Type | string | Package type (e.g., library, composer-plugin) |
Repository | string | Corresponding source code repository URL |
GithubStars | int | GitHub star count |
GithubWatchers | int | GitHub watcher count |
GithubForks | int | GitHub fork count |
GithubOpenIssues | int | GitHub open issue count |
Language | string | Repository primary language |
Dependents | int | How many other packages depend on this |
Suggesters | int | Suggester count |
Downloads | PackageDownloads | Download stats, see next section |
Favers | int | Favorite count |
📉 PackageDownloads
Download stats, nested in PackageInfo.Downloads and PackageStatsResponse.Downloads.
type PackageDownloads struct {
Total int `json:"total" bson:"total"`
Monthly int `json:"monthly" bson:"monthly"`
Daily int `json:"daily" bson:"daily"`
}| Field | Type | Description |
|---|---|---|
Total | int | Historical total download count |
Monthly | int | Current month download count |
Daily | int | Today's download count |
👤 Maintainer
Package maintainer, element type of PackageInfo.Maintainers.
type Maintainer struct {
Name string `json:"name" bson:"name"`
AvatarURL string `json:"avatar_url" bson:"avatar_url"`
}| Field | Type | Description |
|---|---|---|
Name | string | Maintainer name |
AvatarURL | string | Maintainer avatar URL |
🏷️ Version
Complete metadata for a single version. Value type of PackageInfo.Versions is *Version.
type Version struct {
Name string `json:"name"`
Description string `json:"description"`
Keywords []string `json:"keywords"`
Homepage string `json:"homepage"`
Version string `json:"version"`
VersionNormalized string `json:"version_normalized"`
License []string `json:"license" bson:"license"`
Authors []struct {
Name string `json:"name" bson:"name"`
Email string `json:"email" bson:"email"`
Homepage string `json:"homepage" bson:"homepage"`
} `json:"authors" bson:"authors"`
Source struct {
URL string `json:"url" bson:"url"`
Type string `json:"type" bson:"type"`
Reference string `json:"reference" bson:"reference"`
} `json:"source" bson:"source"`
Dist struct {
URL string `json:"url" bson:"url"`
Type string `json:"type" bson:"type"`
Shasum string `json:"shasum" bson:"shasum"`
Reference string `json:"reference" bson:"reference"`
} `json:"dist" bson:"dist"`
Type string `json:"type" bson:"type"`
Support struct {
Source string `json:"source" bson:"source"`
} `json:"support" bson:"support"`
Funding []struct {
URL string `json:"url" bson:"url"`
Type string `json:"type" bson:"type"`
} `json:"funding" bson:"funding"`
Time time.Time `json:"time" bson:"time"`
Require map[string]string `json:"require" bson:"require"`
Autoload interface{} `json:"autoload" bson:"autoload"`
Extra interface{} `json:"extra" bson:"extra"`
Suggest interface{} `json:"suggest" bson:"suggest"`
Provide interface{} `json:"provide" bson:"provide"`
}| Field | Type | Description |
|---|---|---|
Name | string | Version name |
Description | string | Version description |
Keywords | []string | Keywords |
Homepage | string | Version homepage |
Version | string | Version number (e.g., 6.0.0) |
VersionNormalized | string | Normalized version number |
License | []string | License used by this version |
Authors | []struct | Author list (contains name/email/homepage) |
Source | struct | Source info (url/type/reference) |
Dist | struct | Distribution archive info (url/type/shasum/reference) |
Type | string | Package type |
Support | struct | Support info (contains source link) |
Funding | []struct | Funding info (url/type) |
Time | time.Time | Version release time |
Require | map[string]string | Other packages and version constraints this version depends on |
Autoload | interface{} | PSR-4 etc. autoloading config |
Extra | interface{} | Extra config |
Suggest | interface{} | Suggested packages to install |
Provide | interface{} | Virtual package capabilities this version provides |
Authors/Source/Dist are anonymous structs
Authors, Source, Dist, Support, Funding are all inline anonymous structs, cannot be referenced by type externally. To reuse their fields, use chain access like version.Authors[i].Name.
🚀 Example: Iterate Package Versions and Dependencies
package main
import (
"fmt"
"log"
"time"
"github.com/scagogogo/composer-skills/pkg/client"
)
func main() {
c := client.NewComposerClient(30 * time.Second)
info, err := c.GetPackage("monolog/monolog")
if err != nil {
log.Fatal(err)
}
fmt.Printf("Maintainers: %d people\n", len(info.Package.Maintainers))
for ver, v := range info.Package.Versions {
fmt.Printf("Version %s, license=%v, dependency count=%d\n", ver, v.License, len(v.Require))
for dep, constraint := range v.Require {
fmt.Printf(" - %s: %s\n", dep, constraint)
}
}
}📚 Related Documentation
- 🔙 Back to Domain Overview
- 🔒 Security advisory fields → advisory.md
- 📊 Single package download stats → statistics.md