🏗️ Repository 层
pkg/repository 是 Packagist API 的一个底层 HTTP 调用实现。它直接对接 Packagist 的 REST 端点,返回反序列化后的领域模型。
何时使用
- 你需要更细粒度的控制(自定义
context.Context、代理)。 - 你想直接调用 Packagist 端点,而不经过
pkg/client.ComposerClient。 - 你在构建包镜像或索引下载服务。
pkg/client 与 pkg/repository 是两个并行的 Packagist 访问实现。
ComposerClient 自行发起 HTTP 请求(基于 repoURL/baseURL),覆盖了完整的高层 API;Repository 提供基于 context 的底层方法。日常开发用 Client 即可,需要 context 传透或代理控制时再用 Repository 层。
核心类型
Repository
type Repository struct {
options *Options
}Repository 持有 Options(服务地址、代理),所有方法都通过它发起 HTTP 请求。由于 options 字段未导出,外部包以零值字面量构造(与 examples/ 中的用法一致):
repo := &repository.Repository{}构造后即可调用各方法 —— 方法接收完整的端点 URL 作为参数(如 Statistics 内部请求 https://packagist.org/statistics.json),不依赖 options 中的服务地址。
关于代理
Repository.getBytes 在 options.Proxy 非空时会启用代理,但 options 字段未导出,外部目前无法直接设置代理。如需代理,请使用 pkg/client(支持 WithRepoURL 等选项),或在包内通过测试 helper 构造。
方法清单
| 方法 | 签名 | 说明 |
|---|---|---|
Statistics | (ctx context.Context) (*domain.StatisticsResponse, error) | 获取 Packagist 全局统计 |
List | (ctx context.Context) ([]*Package, error) | 列出所有包名 |
ListSecurityAdvisories | (ctx context.Context, updatedSince time.Time) (*domain.AdvisoriesResponse, error) | 列出指定时间之后更新的安全公告 |
ListAdvisories | (ctx context.Context, packageName string) ([]*domain.Advisory, error) | 列出某个包的安全公告 |
DownloadIndex | (ctx context.Context) ([]byte, error) | 下载包索引原始字节 |
DownloadIndexToFile | (ctx context.Context, filepath string) error | 下载包索引并写入文件 |
Package
type Package struct {
Name string
}List 返回的轻量包模型,只含包名。
示例
package main
import (
"context"
"fmt"
"time"
"github.com/scagogogo/composer-skills/pkg/repository"
)
func main() {
repo := &repository.Repository{}
// 全局统计
stats, _ := repo.Statistics(context.Background())
fmt.Printf("总包数: %d\n", stats.Totals.Packages)
// 增量安全公告(最近 24 小时)
since := time.Now().Add(-24 * time.Hour)
advs, _ := repo.ListSecurityAdvisories(context.Background(), since)
fmt.Printf("最近 24h 公告: %d 条\n", len(advs.Advisories))
// 下载包索引到本地文件
_ = repo.DownloadIndexToFile(context.Background(), "/tmp/packagist-index.json")
}内部机制
Repository 内部用泛型函数 getJson[T] 统一处理请求与反序列化:
func getJson[T any](ctx context.Context, repository *Repository, targetUrl string) (T, error)因此新增一个端点只需声明返回类型并复用 getJson,无需重复 HTTP 样板代码。
ListAdvisories 与 ListSecurityAdvisories 的区别
ListSecurityAdvisories 按更新时间增量拉取全部公告;ListAdvisories 按包名查询单个包的公告。