Skip to content

🏗️ Repository 层

pkg/repository 是 Packagist API 的一个底层 HTTP 调用实现。它直接对接 Packagist 的 REST 端点,返回反序列化后的领域模型。

何时使用

  • 你需要更细粒度的控制(自定义 context.Context、代理)。
  • 你想直接调用 Packagist 端点,而不经过 pkg/client.ComposerClient
  • 你在构建包镜像或索引下载服务。

pkg/clientpkg/repository 是两个并行的 Packagist 访问实现。

ComposerClient 自行发起 HTTP 请求(基于 repoURL/baseURL),覆盖了完整的高层 API;Repository 提供基于 context 的底层方法。日常开发用 Client 即可,需要 context 传透或代理控制时再用 Repository 层。

核心类型

Repository

go
type Repository struct {
    options *Options
}

Repository 持有 Options(服务地址、代理),所有方法都通过它发起 HTTP 请求。由于 options 字段未导出,外部包以零值字面量构造(与 examples/ 中的用法一致):

go
repo := &repository.Repository{}

构造后即可调用各方法 —— 方法接收完整的端点 URL 作为参数(如 Statistics 内部请求 https://packagist.org/statistics.json),不依赖 options 中的服务地址。

关于代理

Repository.getBytesoptions.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

go
type Package struct {
    Name string
}

List 返回的轻量包模型,只含包名。

示例

go
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] 统一处理请求与反序列化:

go
func getJson[T any](ctx context.Context, repository *Repository, targetUrl string) (T, error)

因此新增一个端点只需声明返回类型并复用 getJson,无需重复 HTTP 样板代码。

ListAdvisoriesListSecurityAdvisories 的区别

ListSecurityAdvisories更新时间增量拉取全部公告;ListAdvisories包名查询单个包的公告。

进阶

  • 自定义代理与服务地址:见 Options
  • 索引下载常用于构建 包镜像
  • 高层门面对比:见 Client

基于 MIT 许可证发布