Help us shape the future of Go! Take the 2026 Go Developer Survey

extension

package
v1.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 26, 2026 License: AGPL-3.0 Imports: 19 Imported by: 0

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

View Source
const (
	// GroupLumo 是核心与默认主题使用的 API 分组。
	GroupLumo = "io.github.feibaikin.lumo"
	// VersionAlpha 是 v1 统一使用的版本;语义稳定后再升 v1beta1 / v1。
	VersionAlpha = "v1alpha1"
)

核心自用的分组与版本。插件另起分组,版本沿用同一套形态。

View Source
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 拦下。

View Source
const (
	MaxGroupLen    = 253
	MaxVersionLen  = 32
	MaxKindLen     = 63
	MaxResourceLen = 64
	MaxNameLen     = 253
)

长度上限。group 与 name 取 DNS 名上限,kind 取一个标识符够用的长度。

View Source
const Name = "extension"

Name 是模块名,也是迁移版本表的后缀(goose_db_version_extension)。

Variables

View Source
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

func Resource(kind string) string

Resource 把 kind 映射成 URL 里的复数段。

规则是「小写后加复数后缀」,与英语语法只是近似:URL 段是寻址用的机器标识, 可预测比读起来地道更重要:规则只看后缀,不认英语里的不规则复数。

映射**不可逆**——Movie 与 Movy 都得到 movies。因此反向寻址一律靠数据库里存下的 resource 列,而不是在 Go 侧从复数段猜单数形;kind 也因此必须由创建方显式给出。

func ValidateGroup

func ValidateGroup(group string) error

ValidateGroup 校验 API 分组形态。

func ValidateKind

func ValidateKind(kind string) error

ValidateKind 校验 kind 形态。

func ValidateName

func ValidateName(name string) error

ValidateName 校验记录名形态。

func ValidateResource

func ValidateResource(resource string) error

ValidateResource 校验 URL 里的复数段形态。

func ValidateVersion

func ValidateVersion(version string) error

ValidateVersion 校验 API 版本形态。

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

func (e *Extension) APIVersion() string

APIVersion 返回 Kubernetes 风格的 group/version 串,供客户端识别记录来源。

type Handler

type Handler struct {
	// contains filtered or unexported fields
}

Handler 提供 Extension 平面的通用 CRUD。

func NewHandler

func NewHandler(store *Store) *Handler

NewHandler 构造 Handler。

func (*Handler) Register

func (h *Handler) Register(extension huma.API)

Register 挂载接口。

五个操作都要求 extensions:manage:扩展记录是站点级数据,不存在「自己的记录」 这种所有权概念;读也一样要权限——spec 里可能是任何东西,不该对每个登录用户默认可见。

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 New

func New() *Module

New 构造模块。

func (*Module) Migrations

func (m *Module) Migrations() fs.FS

Migrations 实现 app.Migrator。

func (*Module) Name

func (m *Module) Name() string

Name 实现 app.Module。

func (*Module) Permissions

func (m *Module) Permissions() []app.Permission

Permissions 实现 app.PermissionProvider。

func (*Module) Register

func (m *Module) Register(a *app.App) error

Register 实现 app.Module:只做装配,不访问数据库。

func (*Module) Routes

func (m *Module) Routes(r app.Router)

Routes 实现 app.RouteProvider。

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 Ref

type Ref struct {
	Group    string
	Version  string
	Resource string
	Name     string
}

Ref 是一条记录的寻址四元组,资源段为 URL 里的复数形式。

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 NewStore

func NewStore(db *bun.DB) *Store

NewStore 构造 Store。

func (*Store) Create

func (s *Store) Create(ctx context.Context, e *Extension) error

Create 写入一条记录,resource 由 kind 推导。

func (*Store) Delete

func (s *Store) Delete(ctx context.Context, ref Ref) error

Delete 按地址删除一条记录。

func (*Store) Get

func (s *Store) Get(ctx context.Context, ref Ref) (*Extension, error)

Get 按地址取一条记录。

func (*Store) KindOf

func (s *Store) KindOf(ctx context.Context, ref Ref) (string, error)

KindOf 返回某个资源段上已登记的 kind;该资源段还没有记录时返回空串。

用于挡住「同一地址两种 kind」:Replicaset 与 ReplicaSet 都映射到 replicasets, 先写入的那个即为该资源段的正规拼法。

func (*Store) List

func (s *Store) List(ctx context.Context, params *ListParams) ([]Extension, int, error)

List 分页返回某个资源下的记录,并给出总数。

func (*Store) Update

func (s *Store) Update(ctx context.Context, e *Extension) error

Update 整体替换一条记录的 spec;地址与 kind 不可改。

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL