resources

package
v2.0.0-...-51e8ac7 Latest Latest
Warning

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

Go to latest
Published: Aug 25, 2026 License: MIT Imports: 11 Imported by: 0

Documentation

Overview

Package resources provides v2 resource registration with seven standard CRUD operations, inspired by Buffalo's resource pattern.

A Resource defines the seven operations:

  • List: GET /{resource}
  • Show: GET /{resource}/{id}
  • New: GET /{resource}/new
  • Create: POST /{resource}
  • Edit: GET /{resource}/{id}/edit
  • Update: PUT /{resource}/{id}
  • Destroy: DELETE /{resource}/{id}

PATCH is an optional alias of Update, not a separate seventh operation.

Each operation is independently typed with its own request and response types via handlers.Endpoint[Req, Resp], providing compile-time type safety. Operations that are not supported return nil and are registered with a default 405 response via ResourceDefaults.

Two resource interfaces are provided:

  • Resource[ID]: the recommended interface for v2 migration. Each operation returns handlers.EndpointRuntime. Implement this for simple CRUD + custom (non-CRUD) resources. Pair with ResourceBuilder for fluent registration.
  • TypedResource[ID, ...]: advanced interface with per-operation type parameters (14 type params). Each operation returns a fully typed *handlers.Endpoint[Req, Resp]. This is overkill for most resources — use it only when you need the strictest compile-time guarantees on every operation's request/response types. Any TypedResource automatically satisfies Resource[ID].

For v2 migration, the recommended path is:

resources.NewResource[string]("/users").            // ResourceBuilder
    EnablePatch().
    WithCustom(reloadOp).
    Register(router, core, respHandler, &UserResource{}) // implements Resource[ID]

Avoid TypedResource unless you have a specific need for 14-type-parameter strictness — the verbosity outweighs the benefit for simple CRUD resources.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func GetParsedID

func GetParsedID[ID cmp.Ordered](ctx *v2wf.RequestContext, idParam string) (ID, error)

GetParsedID retrieves a parsed ID from the request context's locals. This is used by resource handlers to access the ID parsed by withIDParser. The RequestContext is available on the HandlerRequest's V2 field.

func Register

func Register[ID cmp.Ordered](router routing.RouteGroup, config Config[ID]) error

Register registers all seven resource operations on the given router. Static routes (/new, /{id}/edit) are registered before /{id} routes to ensure correct precedence on all adapters.

Types

type Config

type Config[ID cmp.Ordered] struct {
	// Path is the base path for the resource (e.g. "/users").
	Path string

	// Resource implements the seven operations.
	Resource Resource[ID]

	// Core is the v1 RequestCoreInterface for infrastructure access.
	// May be nil for pure v2 applications.
	Core requestCore.RequestCoreInterface

	// RespHandler is the v2 response handler.
	RespHandler *v2response.Handler

	// IDParam is the URL parameter name for the resource ID.
	// Default: "id".
	IDParam string

	// IDParser converts a string URL parameter to the ID type.
	// If nil, the string value is used directly for string IDs.
	IDParser func(string) (ID, error)

	// EnablePatchAlias, when true, registers PATCH as an alias for
	// Update on the /{id} path.
	EnablePatchAlias bool

	// Defaults provides 405 handlers for unsupported operations.
	// If nil, unsupported operations are silently skipped.
	Defaults *ResourceDefaults

	// Custom registers non-CRUD operations (e.g. Reload, Validate)
	// alongside the standard 7 operations. Custom operations are
	// registered before /{id} routes for correct path precedence.
	Custom []CustomOperation
}

Config holds the configuration for registering a resource.

type CustomOperation

type CustomOperation struct {
	// Method is the HTTP method (GET, POST, PUT, DELETE, PATCH).
	Method string

	// Path is the sub-path appended to the resource base path.
	// Must start with "/". For example: "/reload", "/validate".
	Path string

	// Endpoint is the typed endpoint descriptor for the operation.
	Endpoint handlers.EndpointRuntime
}

CustomOperation defines a non-CRUD action registered alongside a resource. Common use cases include Reload, Validate, Approve, or other domain-specific actions that don't fit the 7 standard operations.

The Path is appended to the resource's base Path. For example, if the resource Path is "/parameters" and the CustomOperation Path is "/reload", the full route is "POST /parameters/reload".

Custom operations are registered before /{id} routes to ensure correct precedence (e.g. "/parameters/reload" won't match "/{id}").

type Resource

type Resource[ID cmp.Ordered] interface {
	// List returns a list of resources.
	List() handlers.EndpointRuntime
	// Show returns a single resource by ID.
	Show() handlers.EndpointRuntime
	// New returns the form/data for creating a new resource.
	New() handlers.EndpointRuntime
	// Create creates a new resource.
	Create() handlers.EndpointRuntime
	// Edit returns the form/data for editing a resource by ID.
	Edit() handlers.EndpointRuntime
	// Update replaces a resource by ID.
	Update() handlers.EndpointRuntime
	// Destroy deletes a resource by ID.
	Destroy() handlers.EndpointRuntime
}

Resource defines the seven standard CRUD operations for a resource. Each operation returns an EndpointRuntime — a type-erased interface that can be registered on a router. Operations returning nil are not supported and will be registered with a default 405 handler.

ID must be cmp.Ordered (string, int, int64, float64, etc.) to ensure IDs can be compared and sorted at compile time.

type ResourceBuilder

type ResourceBuilder[ID cmp.Ordered] struct {
	// contains filtered or unexported fields
}

ResourceBuilder provides a fluent API for constructing and registering resources. It is the recommended way to register resources in v2 application code — prefer it over passing raw Config[ID] to Register.

The typical v2 migration path is:

resources.NewResource[string]("/users").
    EnablePatch().
    WithCustom(reloadOp).
    Register(router, core, respHandler, &UserResource{})

where UserResource implements Resource[string] (not TypedResource).

func NewResource

func NewResource[ID cmp.Ordered](path string) *ResourceBuilder[ID]

NewResource creates a ResourceBuilder for the given base path. The ID type parameter must be cmp.Ordered (string, int, int64, etc.).

func (*ResourceBuilder[ID]) EnablePatch

func (b *ResourceBuilder[ID]) EnablePatch() *ResourceBuilder[ID]

EnablePatch enables PATCH as an alias for Update on the /{id} path.

func (*ResourceBuilder[ID]) Register

func (b *ResourceBuilder[ID]) Register(
	router routing.RouteGroup,
	core requestCore.RequestCoreInterface,
	respHandler *v2response.Handler,
	resource Resource[ID],
) error

Register registers all resource operations on the given router using the builder's configuration.

func (*ResourceBuilder[ID]) WithCustom

func (b *ResourceBuilder[ID]) WithCustom(ops ...CustomOperation) *ResourceBuilder[ID]

WithCustom adds custom (non-CRUD) operations to the resource.

func (*ResourceBuilder[ID]) WithDefaults

func (b *ResourceBuilder[ID]) WithDefaults(d *ResourceDefaults) *ResourceBuilder[ID]

WithDefaults sets the ResourceDefaults for 405 handlers on unsupported operations.

func (*ResourceBuilder[ID]) WithIDParam

func (b *ResourceBuilder[ID]) WithIDParam(name string) *ResourceBuilder[ID]

WithIDParam sets the URL parameter name for the resource ID. Default: "id".

func (*ResourceBuilder[ID]) WithIDParser

func (b *ResourceBuilder[ID]) WithIDParser(fn func(string) (ID, error)) *ResourceBuilder[ID]

WithIDParser sets a custom ID parser function.

type ResourceDefaults

type ResourceDefaults struct{}

ResourceDefaults holds default endpoint handlers for unsupported operations. When a Resource returns nil for an operation, the corresponding default handler emits a 405 Method Not Allowed response.

type TypedResource

type TypedResource[
	ID cmp.Ordered,
	ListReq, ListResp any,
	ShowReq, ShowResp any,
	NewReq, NewResp any,
	CreateReq, CreateResp any,
	EditReq, EditResp any,
	UpdateReq, UpdateResp any,
	DestroyReq, DestroyResp any,
] interface {
	List() *handlers.Endpoint[ListReq, ListResp]
	Show() *handlers.Endpoint[ShowReq, ShowResp]
	New() *handlers.Endpoint[NewReq, NewResp]
	Create() *handlers.Endpoint[CreateReq, CreateResp]
	Edit() *handlers.Endpoint[EditReq, EditResp]
	Update() *handlers.Endpoint[UpdateReq, UpdateResp]
	Destroy() *handlers.Endpoint[DestroyReq, DestroyResp]
}

TypedResource is an advanced resource interface with per-operation type parameters. Implementing this interface gives compile-time type safety for all 7 operations — each operation returns a fully typed *handlers.Endpoint[Req, Resp].

Any TypedResource automatically satisfies Resource[ID] because *handlers.Endpoint[Req, Resp] implements handlers.EndpointRuntime.

The 14 type parameters (7 request + 7 response types) make this verbose to spell out. For most v2 migration use cases (simple CRUD + custom operations like Reload), prefer Resource[ID] with ResourceBuilder — the 14 type parameters are overkill. Use TypedResource only when you need the strictest compile-time guarantees on every operation's request/response types simultaneously.

Jump to

Keyboard shortcuts

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