Skip to content

📊 统计模型

pkg/domain 中描述 Packagist 统计与变更跟踪数据的结构体。对应以下接口:

  • https://packagist.org/statistics.jsonStatisticsResponse
  • https://packagist.org/packages/<vendor>/<name>/stats.jsonPackageStatsResponse
  • https://packagist.org/metadata/changes.json?since=<timestamp>ChangeTrackingResponse

类型总览

类型角色来源接口
StatisticsResponse仓库整体统计顶层/statistics.json
Totals仓库总量(下载/包/版本)嵌套于 StatisticsResponse
PackageStatsResponse单包下载统计/<package>/stats.json
ChangeTrackingResponse元数据变更跟踪响应/metadata/changes.json
ChangeAction单条变更操作嵌套于 ChangeTrackingResponse

📈 StatisticsResponse

Packagist 仓库整体统计的顶层结构。

go
type StatisticsResponse struct {
    Totals Totals `json:"totals"`
}
字段类型说明
TotalsTotals仓库总计统计,见下节

🔢 Totals

仓库总体统计信息。

go
type Totals struct {
    Downloads int64 `json:"downloads"`
    Packages  int   `json:"packages"`
    Versions  int   `json:"versions"`
}
字段类型说明示例
Downloadsint64所有包的总下载次数10000000000
Packagesint仓库中的包总数300000
Versionsint所有包的版本总数2500000

Downloads 用 int64

全站下载量级可达百亿,超过 32 位 int 范围,因此 Downloads 显式使用 int64。做累加或比较时请勿赋给 int 变量(在 32 位平台上会溢出)。


📉 PackageStatsResponse

单个包的下载统计。Downloads 字段复用了 package.md 中的 PackageDownloads 类型。

go
type PackageStatsResponse struct {
    Downloads PackageDownloads `json:"downloads"`
    Versions  []string         `json:"versions"`
    Date      string           `json:"date"`
}
字段类型说明
DownloadsPackageDownloads下载统计(Total/Monthly/Daily)
Versions[]string可用版本列表
Datestring统计开始日期

🔄 ChangeTrackingResponse

元数据变更跟踪响应。用于增量同步:传入一个 since 时间戳,Packagist 返回该时间点之后的所有包变更操作。

go
type ChangeTrackingResponse struct {
    Error     string          `json:"error,omitempty"`
    Timestamp int64           `json:"timestamp"`
    Actions   []ChangeAction  `json:"actions,omitempty"`
}
字段类型说明
Errorstringsince 参数缺失或无效时返回的错误信息(正常时为空)
Timestampint64当前响应的时间戳(Unix 秒)
Actions[]ChangeAction变更操作列表,见下节

增量同步模式

典型用法:本地保存上次的 Timestamp,下次请求时作为 since 传入,逐步追赶 Actions 中的 update/delete。若 Error 非空,说明 since 过期或无效,需重新全量同步。


⚡ ChangeAction

单条变更操作。

go
type ChangeAction struct {
    Type    string `json:"type"`
    Package string `json:"package"`
    Time    int64  `json:"time"`
}
字段类型说明取值
Typestring操作类型"update""delete"
Packagestring被操作的包名symfony/console
Timeint64操作发生时间的 Unix 时间戳1700000000

🚀 示例

仓库总量统计

go
package main

import (
    "fmt"
    "log"
    "time"

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

func main() {
    c := client.NewComposerClient(30 * time.Second)
    stats, err := c.GetStatistics()
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("包总数: %d\n", stats.Totals.Packages)
    fmt.Printf("版本总数: %d\n", stats.Totals.Versions)
    fmt.Printf("总下载量: %d\n", stats.Totals.Downloads)
}

单包下载统计

go
stats, _ := c.GetPackageStats("monolog/monolog")
fmt.Printf("今日下载: %d, 本月: %d, 总计: %d\n",
    stats.Downloads.Daily, stats.Downloads.Monthly, stats.Downloads.Total)

增量变更跟踪

go
package main

import (
    "context"
    "fmt"
    "log"

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

func main() {
    c := client.NewComposerClient(60)
    var since int64 = 1700000000 // 上次同步的时间戳

    changes, err := c.GetPackageChanges(context.Background(), since)
    if err != nil {
        log.Fatal(err)
    }
    if changes.Error != "" {
        log.Fatalf("API 返回错误: %s(since 可能已过期,需全量同步)", changes.Error)
    }
    fmt.Printf("当前时间戳: %d, 变更数: %d\n", changes.Timestamp, len(changes.Actions))
    for _, a := range changes.Actions {
        fmt.Printf("  [%s] %s @ %d\n", a.Type, a.Package, a.Time)
    }
    // 下次用 changes.Timestamp 作为新的 since
}

📚 相关文档

基于 MIT 许可证发布