Documentation
¶
Overview ¶
Package extension 实现 Extension 平面的通用 CRUD。
Extension 是给插件预留的自定义模型:核心不解释 spec 里有什么,只负责寻址、 校验命名与持久化。一条记录由 (apiGroup, version, kind, name) 唯一确定, 地址形如 /apis/io.github.feibaikin.lumo/v1alpha1/posts/hello。
表 extensions 在核心迁移里就建好了,本模块只补一列 resource 与按它寻址的唯一索引: 地址里是复数段而表里存单数 kind,映射规则在 Go 侧且不可逆,故把结果存下来。
Index ¶
- Constants
- Variables
- func Resource(kind string) string
- func ValidateGroup(group string) error
- func ValidateKind(kind string) error
- func ValidateName(name string) error
- func ValidateResource(resource string) error
- func ValidateVersion(version string) error
- type Extension
- type Handler
- type ListParams
- type Module
- type NameParam
- type Ref
- type ResourceParams
- type Store
- func (s *Store) Create(ctx context.Context, e *Extension) error
- func (s *Store) Delete(ctx context.Context, ref Ref) error
- func (s *Store) Get(ctx context.Context, ref Ref) (*Extension, error)
- func (s *Store) KindOf(ctx context.Context, ref Ref) (string, error)
- func (s *Store) List(ctx context.Context, params *ListParams) ([]Extension, int, error)
- func (s *Store) Update(ctx context.Context, e *Extension) error
Constants ¶
const ( // GroupLumo 是核心与默认主题使用的 API 分组。 GroupLumo = "io.github.feibaikin.lumo" // VersionAlpha 是 v1 统一使用的版本;语义稳定后再升 v1beta1 / v1。 VersionAlpha = "v1alpha1" )
核心自用的分组与版本。插件另起分组,版本沿用同一套形态。
const ( // GroupPattern 是反向域名:至少两段,段间以点分隔。 GroupPattern = `^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)+$` // VersionPattern 覆盖 v1alpha1 / v1beta2 / v1 三种形态。 VersionPattern = `^v[1-9]\d*((alpha|beta)[1-9]\d*)?$` // ResourcePattern 是 URL 里的复数段:由 kind 小写后加复数后缀而来,故不含连字符。 ResourcePattern = `^[a-z][a-z0-9]*$` // KindPattern 是单数 PascalCase。 KindPattern = `^[A-Z][A-Za-z0-9]*$` // NamePattern 是 DNS-1123,与核心迁移里的 extensions_name_dns1123 约束一致。 NamePattern = `^[a-z0-9]([-a-z0-9]*[a-z0-9])?$` )
命名形态。这些模式同时写进 OpenAPI 的参数声明, 形态不合法的地址在进入处理器之前就被 huma 拦下。
const ( MaxGroupLen = 253 MaxVersionLen = 32 MaxKindLen = 63 MaxResourceLen = 64 MaxNameLen = 253 )
长度上限。group 与 name 取 DNS 名上限,kind 取一个标识符够用的长度。
const Name = "extension"
Name 是模块名,也是迁移版本表的后缀(goose_db_version_extension)。
Variables ¶
var ( // ErrNotFound 表示记录不存在。 ErrNotFound = errors.New("扩展记录不存在") // ErrNameTaken 表示同一资源下已有同名记录。 ErrNameTaken = errors.New("同名扩展记录已存在") // ErrKindConflict 表示该资源段已被另一种拼法的 kind 占用。 ErrKindConflict = errors.New("资源段已被另一个 kind 占用") // ErrInvalid 表示字段形态不合法或违反了数据库约束。 ErrInvalid = errors.New("字段不合法") )
错误哨兵。处理器据此映射为 404 / 409 / 422。
Functions ¶
func Resource ¶
Resource 把 kind 映射成 URL 里的复数段。
规则是「小写后加复数后缀」,与英语语法只是近似:URL 段是寻址用的机器标识, 可预测比读起来地道更重要:规则只看后缀,不认英语里的不规则复数。
映射**不可逆**——Movie 与 Movy 都得到 movies。因此反向寻址一律靠数据库里存下的 resource 列,而不是在 Go 侧从复数段猜单数形;kind 也因此必须由创建方显式给出。
func ValidateResource ¶
ValidateResource 校验 URL 里的复数段形态。
Types ¶
type Extension ¶
type Extension struct {
bun.BaseModel `bun:"table:extensions,alias:ext"`
ID int64 `bun:"id,pk,autoincrement" json:"id"`
APIGroup string `bun:"api_group,notnull" json:"apiGroup" doc:"反向域名形式的 API 分组"`
Version string `bun:"version,notnull" json:"version" doc:"API 版本,如 v1alpha1"`
Kind string `bun:"kind,notnull" json:"kind" doc:"单数 PascalCase 的资源种类"`
Resource string `bun:"resource,notnull" json:"resource" doc:"URL 里的复数段,由 kind 推导"`
Name string `bun:"name,notnull" json:"name" doc:"DNS-1123 名称,在同一资源下唯一"`
// Spec 是自定义字段,核心不解释其内容,只整体存取。
Spec map[string]any `bun:"spec,type:jsonb" json:"spec" doc:"自定义字段,服务端不解释其内容"`
CreatedAt time.Time `bun:"created_at,nullzero" json:"createdAt"`
UpdatedAt time.Time `bun:"updated_at,nullzero" json:"updatedAt"`
// SelfLink 是本记录的访问地址,不是数据库列。
//
// 由服务端给出而不是让客户端自己拼:kind 到复数段的映射规则在服务端,
// 通用客户端拿到一条记录就该知道它住在哪儿。
SelfLink string `bun:"-" json:"selfLink" doc:"本记录的 Extension 平面地址"`
}
Extension 是 Extension 平面上的一条记录。
表在核心迁移里就建好了(migrations/00001_init.sql),本模块只补一列 resource 与按它寻址的唯一索引,见 migrations/00001_extension.sql。
func (*Extension) APIVersion ¶
APIVersion 返回 Kubernetes 风格的 group/version 串,供客户端识别记录来源。
type Handler ¶
type Handler struct {
// contains filtered or unexported fields
}
Handler 提供 Extension 平面的通用 CRUD。
type ListParams ¶
type ListParams struct {
Group string
Version string
Resource string
// Match 是对 spec 的包含匹配(jsonb @>),走核心迁移建好的 GIN 索引。
Match map[string]any
// Sort 是排序方式,取值见 sortExpr。
Sort string
Page api.PageParams
}
ListParams 是列表查询条件。
type Module ¶
type Module struct {
// contains filtered or unexported fields
}
Module 是扩展记录模块。
func (*Module) Permissions ¶
func (m *Module) Permissions() []app.Permission
Permissions 实现 app.PermissionProvider。
type NameParam ¶
type NameParam struct {
Name string `path:"name" maxLength:"253" pattern:"^[a-z0-9]([-a-z0-9]*[a-z0-9])?$" doc:"DNS-1123 名称"`
}
NameParam 是记录名路径参数。
type ResourceParams ¶
type ResourceParams struct {
Group string `` /* 175-byte string literal not displayed */
Version string `path:"version" maxLength:"32" pattern:"^v[1-9]\\d*((alpha|beta)[1-9]\\d*)?$" doc:"API 版本,如 v1alpha1"`
Resource string `path:"resource" maxLength:"64" pattern:"^[a-z][a-z0-9]*$" doc:"kind 的小写复数形式,如 posts"`
}
ResourceParams 是三段寻址前缀,嵌入到各输入结构体。
模式同时写进 OpenAPI 的参数声明,形态不合法的地址由 huma 在进入处理器之前拦下。
type Store ¶
type Store struct {
// contains filtered or unexported fields
}
Store 提供扩展记录的持久化操作。
func (*Store) KindOf ¶
KindOf 返回某个资源段上已登记的 kind;该资源段还没有记录时返回空串。
用于挡住「同一地址两种 kind」:Replicaset 与 ReplicaSet 都映射到 replicasets, 先写入的那个即为该资源段的正规拼法。