payloadcms

package module
v0.0.6 Latest Latest
Warning

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

Go to latest
Published: Feb 10, 2025 License: MIT Imports: 16 Imported by: 1

README

Go Payload CMS

GoLang client library & SDK for Payload CMS

Go Report Card Maintainability GoDoc Test Lint
codecov ainsley.dev Twitter Handle

Introduction

Go Payload is a GoLang client library for Payload CMS. It provides a simple and easy-to-use interface for interacting with the Payload CMS API by saving you the hassle of dealing with unmarshalling JSON responses into your Payload collections and globals.

Installation

go get -u github.com/ainsleyclark/go-payloadcms

Quick Start

import (
	"github.com/ainsleyclark/go-payloadcms"
)

type Entity struct {
	ID    int    `json:"id"`
	Email string `json:"email"`
	Name  string `json:"name"`
	// ... other fields
}

func main() {
	client, err := payloadcms.New(
		payloadcms.WithBaseURL("http://localhost:8080"),
		payloadcms.WithAPIKey("api-key"),
	)
	
	if err != nil {
		log.Fatalln(err)
	}
	
	var entities payloadcms.ListResponse[Entity]
	resp, err := client.Collections.List(context.Background(), "users", payloadcms.ListParams{}, &entities)
	if err != nil {
		log.Fatalln(err)
	}
	
	fmt.Printf("Received status: %d, with body: %s\n", resp.StatusCode, string(resp.Content))
}

Docs

Documentation can be found at the Go Docs, but we have included a kick-start guide below to get you started.

Services

The client provides the services as defined below. Each

  • Collections
  • Globals
  • Media

Collections

The collections service provides methods to interact with the collections in Payload CMS. For more information please visit the docs here.

FindByID
var entity Entity // Any struct that conforms to your collection schema.
resp, err := client.Collections.FindByID(context.Background(), "collection", 1, &entity)
if err != nil {
	fmt.Println(err)
	return
}
List
var entities payloadcms.ListResponse[Entity] // Must use ListResponse with generic type.
resp, err := client.Collections.List(context.Background(), "collection", payloadcms.ListParams{
	Sort:  "-createdAt",
	Limit: 10,
	Page:  1,
}, entities)
if err != nil {
	fmt.Println(err)
	return
}
Create
var entity Entity // Any struct representing the entity to be created.
resp, err := client.Collections.Create(context.Background(), "collection", entity)
if err != nil {
	fmt.Println(err)
	return
}
fmt.Println(string(resp.Content)) // Can unmarshal into response struct if needed.
UpdateByID
var entity Entity // Any struct representing the updated entity.
resp, err := client.Collections.UpdateByID(context.Background(), "collection", 1, entity)
if err != nil {
	fmt.Println(err)
	return
}
fmt.Println(string(resp.Content)) // Can unmarshal into response struct if needed.
DeleteByID
resp, err := client.Collections.DeleteByID(context.Background(), "collection", 1)
if err != nil {
	fmt.Println(err)	
	return
}
// Use response data as needed

Globals

The globals service provides methods to interact with the globals in Payload CMS. For more information please visit the docs here.

Get
var global Global // Any struct representing a global type.
resp, err := client.Globals.Get(context.Background(), "global", &global)
if err != nil {
	fmt.Println(err)
	return
}
Update
var global Global // Any struct representing a global type.
resp, err := client.Globals.Update(context.Background(), "global", global)
if err != nil {
	fmt.Println(err)
	return
}
fmt.Println(string(resp.Content)) // Can unmarshal into response struct if needed.

Media

The media service provides methods to upload media types to Payload CMS. For more information please visit the docs here.

Upload
file, err := os.Open("path/to/file")
if err != nil {
	fmt.Println(err)
	return
}

media := &payloadcms.CreateResponse[Media]{}
_, err = m.payload.Media.UploadFromURL(ctx, file, Media{Alt: "alt"}, &media, payloadcms.MediaOptions{
	Collection:       "media",
})

if err != nil {
	fmt.Println(err)
	return
}
UploadFromURL
media := &payloadcms.CreateResponse[Media]{}
_, err = m.payload.Media.UploadFromURL(ctx, "https://payloadcms.com/picture-of-cat.jpg", Media{Alt: "alt"}, &media, payloadcms.MediaOptions{
	Collection:       "media",
})

if err != nil {
	fmt.Println(err)
	return
}
Queries

The Params allows you to add filters, sort order, pagination, and other query parameters. Here's an example:

import (
	"context"
	"fmt"
	"github.com/ainsleyclark/go-payloadcms"
)

func main() {
	client, err := payloadcms.New(
		payloadcms.WithBaseURL("http://localhost:8080"),
		payloadcms.WithAPIKey("api-key"),
	)
	if err != nil {
		log.Fatalln(err)
	}

	var entities payloadcms.ListResponse[Entity]
	
	params := payloadcms.ListParams{
		Sort: "-createdAt",          
		Limit: 10,                  
		Page: 1,                     
		Where: payloadcms.Query().Equals("status", "active").GreaterThan("age", "18"),
	}

	resp, err := client.Collections.List(context.Background(), "users", params, &entities)
	if err != nil {
		log.Fatalln(err)
	}

	fmt.Printf("Received status: %d, with body: %s\n", resp.StatusCode, string(resp.Content))
}

Options

The RequestOption type is a functional option used to configure HTTP requests sent to the Payload CMS API.

WithDepth

WithDepth specifies the depth level for API responses, determining how much nested data is included. See the Payload Website for more details.

Usage:

client.Do(ctx, http.MethodGet, "/api/posts", nil, &out,
    WithDepth(10),
)

This will append ?depth=10 to the request URL.

WithQueryParam

WithQueryParam adds a key, value query parameters to the API request.

Usage:

client.Do(ctx, http.MethodGet, "/api/posts", nil, &out,
    WithQueryParam("category", "tech"),
)

This will append ?category=tech to the request URL.

Mocks

Mock implementations can be found in payloadfakes package located in fakes directory.

They provide mock implementations of all the services provided by the client for convenience.

Example:

func TestPayload(t *testing.T) {
	// Create a new mock collection service
	mockCollectionService := payloadfakes.NewMockCollectionService()
	
	// Define the behavior of the FindByID method
	mockCollectionService.FindByIDFunc = func (ctx context.Context,
		collection payloadcms.Collection,
		id int,
		out any,
	) (payloadcms.Response, error) {
		// Custom logic for the mock implementation
		return payloadcms.Response{}, nil
	}
	
	// Use the mock collection service in your tests
	myFunctionUsingCollectionService(mockCollectionService)
}

Response and Error Types

The library defines custom response and error types to provide a more convenient way to interact with the API.

  • Response: This struct wraps the standard http.Response returned by the API and provides additional fields for easier access to response data and potential errors.
    • Content: The response body bytes.
    • Message: A user-friendly message extracted from the response (if available).
    • Errors: A list of Error structs containing details about any API errors encountered.
  • Error: This struct represents a single API error with a Message field containing the error description.

These types are used throughout the library to handle successful responses and API errors consistently.

Development

Setup

To get set up with Go Payload simply clone the repo and run the following:

make setup

This will install all dependencies and set up the project for development.

Payload Dev Env

Within the ./dev directory, you will find a local instance of Payload CMS that can be used for testing the client. To get setup with Payload, simply follow the steps below.

Copy the environment file and replace where necessary. The postgres-db adapater is currently being used for the database.

cp .env.example .env

Then run the Payload instance like you would any other installation.

pnpm run dev

TODOs

Contributing

Contributions are welcome! If you find any bugs or have suggestions for improvement, please open an issue or submit a pull request.

License

This project is licensed under the MIT License - see the LICENSE file for details.

Trademark

ainsley.dev and the ainsley.dev logo are either registered trademarks or trademarks of ainsley.dev LTD in the United Kingdom and/or other countries. All other trademarks are the property of their respective owners.

Documentation

Index

Constants

View Source
const AllItems = 0

AllItems is a constant that can be used to retrieve all items from a collection. It's defined as 0 in the Payload API.

Variables

This section is empty.

Functions

This section is empty.

Types

type Client

type Client struct {
	// Each collection is mounted using its slug value. For example, if a collection's slug is
	// users, all corresponding routes will be mounted on /api/users.
	// For more info, visit: https://payloadcms.com/docs/rest-api/overview#collections
	Collections CollectionService

	// Globals cannot be created or deleted, so there are only two REST endpoints opened:
	// For more info, visit: https://payloadcms.com/docs/rest-api/overview#globals
	Globals GlobalsService

	// Media is a separate service used to upload and manage media files.
	// For more info, visit: https://payloadcms.com/docs/upload/overview
	Media MediaService
	// contains filtered or unexported fields
}

Client represents a Payload CMS client. For more information, see https://payloadcms.com/docs/api.

func New

func New(options ...ClientOption) (*Client, error)

New creates a new Payload CMS client.

func (*Client) Delete

func (c *Client) Delete(ctx context.Context, path string, v any, opts ...RequestOption) (Response, error)

Delete sends an HTTP DELETE request and returns the API response. The API response is JSON decoded and stored in the value pointed to by v, or returned as an error if an API error has occurred.

func (*Client) Do

func (c *Client) Do(ctx context.Context, method, path string, body any, v any, opts ...RequestOption) (Response, error)

Do sends an API request and returns the API response. The API response is JSON decoded and stored in the value pointed to by v, or returned as an error if an API error has occurred.

Errors occur in the eventuality if the http.StatusCode is not 2xx.

func (*Client) DoWithRequest

func (c *Client) DoWithRequest(_ context.Context, req *http.Request, v any, opts ...RequestOption) (Response, error)

DoWithRequest sends an API request using the provided http.Request and returns the API response. The API response is JSON decoded and stored in the value pointed to by v, or returned as an error if an API error has occurred.

func (*Client) Get

func (c *Client) Get(ctx context.Context, path string, v any, opts ...RequestOption) (Response, error)

Get sends an HTTP GET request and returns the API response. The API response is JSON decoded and stored in the value pointed to by v, or returned as an error if an API error has occurred.

func (*Client) NewFormRequest

func (c *Client) NewFormRequest(ctx context.Context, method, path string, body io.Reader, contentType string) (*http.Request, error)

func (*Client) NewRequest

func (c *Client) NewRequest(ctx context.Context, method, path string, body io.Reader) (*http.Request, error)

NewRequest creates a new Payload API request by using the API Key within the client. A method, path and body is attached to the request.

func (*Client) Patch added in v0.0.5

func (c *Client) Patch(ctx context.Context, path string, in any, opts ...RequestOption) (Response, error)

Patch sends an HTTP PATCH request and returns the API response. The API response is JSON decoded and stored in the value pointed to by v, or returned as an error if an API error has occurred.

func (*Client) Post

func (c *Client) Post(ctx context.Context, path string, in any, opts ...RequestOption) (Response, error)

Post sends an HTTP POST request and returns the API response. The API response is JSON decoded and stored in the value pointed to by v, or returned as an error if an API error has occurred.

func (*Client) Put

func (c *Client) Put(ctx context.Context, path string, in any, opts ...RequestOption) (Response, error)

Put sends an HTTP PUT request and returns the API response. The API response is JSON decoded and stored in the value pointed to by v, or returned as an error if an API error has occurred.

type ClientOption added in v0.0.6

type ClientOption func(*Client)

ClientOption is a functional option type that allows us to configure the Client.

func WithAPIKey

func WithAPIKey(apiKey string) ClientOption

WithAPIKey is a functional option to set the API key for the Payload API. To get an API key, visit: https://payloadcms.com/docs/rest-api/overview#authentication

Usually, you can obtain one by enabling auth on the users type, and visiting the users collection in the Payload dashboard.

func WithBaseURL

func WithBaseURL(url string) ClientOption

WithBaseURL is a functional option to set the base URL of the Payload API. Example: https://api.payloadcms.com

func WithClient

func WithClient(client *http.Client) ClientOption

WithClient is a functional option to set the HTTP client of the Payload API.

type Collection

type Collection string

Collection represents a collection slug from Payload. It's defined as a string under slug within the Collection Config.

const (
	// CollectionUsers defines the Payload users collection slug.
	CollectionUsers Collection = "users"
)

type CollectionService

type CollectionService interface {
	FindByID(ctx context.Context, collection Collection, id int, out any, opts ...RequestOption) (Response, error)
	FindBySlug(ctx context.Context, collection Collection, slug string, out any, opts ...RequestOption) (Response, error)
	List(ctx context.Context, collection Collection, params ListParams, out any, opts ...RequestOption) (Response, error)
	Create(ctx context.Context, collection Collection, in any, opts ...RequestOption) (Response, error)
	UpdateByID(ctx context.Context, collection Collection, id int, in any, opts ...RequestOption) (Response, error)
	DeleteByID(ctx context.Context, collection Collection, id int, opts ...RequestOption) (Response, error)
}

CollectionService is an interface for interacting with the collection endpoints of the Payload API.

See: https://payloadcms.com/docs/rest-api/overview#collections

type CollectionServiceOp

type CollectionServiceOp struct {
	Client *Client
}

CollectionServiceOp handles communication with the collection related methods of the Payload API.

func (CollectionServiceOp) Create

func (s CollectionServiceOp) Create(ctx context.Context, collection Collection, in any, opts ...RequestOption) (Response, error)

Create creates a new collection entity.

func (CollectionServiceOp) DeleteByID

func (s CollectionServiceOp) DeleteByID(ctx context.Context, collection Collection, id int, opts ...RequestOption) (Response, error)

DeleteByID deletes a collection entity by its ID.

func (CollectionServiceOp) FindByID

func (s CollectionServiceOp) FindByID(ctx context.Context, collection Collection, id int, out any, opts ...RequestOption) (Response, error)

FindByID finds a collection entity by its ID.

func (CollectionServiceOp) FindBySlug

func (s CollectionServiceOp) FindBySlug(ctx context.Context, collection Collection, slug string, out any, opts ...RequestOption) (Response, error)

FindBySlug finds a collection entity by its slug. Note: This is not a standard Payload Rest endpoint, but included for convenience. If you want to use this endpoint, you'll need to add an express handler to your Payload config.

func (CollectionServiceOp) List

func (s CollectionServiceOp) List(ctx context.Context, collection Collection, params ListParams, out any, opts ...RequestOption) (Response, error)

List lists all collection entities.

func (CollectionServiceOp) UpdateByID

func (s CollectionServiceOp) UpdateByID(ctx context.Context, collection Collection, id int, in any, opts ...RequestOption) (Response, error)

UpdateByID updates a collection entity by its ID.

type CreateResponse

type CreateResponse[T any] struct {
	Doc     T      `json:"doc"`
	Message string `json:"message"`
	Errors  []any  `json:"errors"`
}

CreateResponse represents a response from the Payload CMS when a new entity is created.

type Error

type Error struct {
	Message string `json:"message"`
}

Error defines a singular API error.

type Errors

type Errors []Error

Errors defines a list of Payload API errors. For Example { "errors": [ { "message": "You are not allowed to perform this action." } ] }

func (Errors) Error

func (e Errors) Error() string

Error implements the error interface to return the error message.

type Global

type Global string

Global represents a global slug from Payload.

type GlobalsService

type GlobalsService interface {
	Get(ctx context.Context, global Global, in any, opts ...RequestOption) (Response, error)
	Update(ctx context.Context, global Global, in any, opts ...RequestOption) (Response, error)
}

GlobalsService is an interface for interacting with the global endpoints of the Payload API.

See: https://payloadcms.com/docs/rest-api/overview#globals

type GlobalsServiceOp

type GlobalsServiceOp struct {
	Client *Client
}

GlobalsServiceOp handles communication with the global related methods of the Payload API.

func (GlobalsServiceOp) Get

func (s GlobalsServiceOp) Get(ctx context.Context, global Global, in any, opts ...RequestOption) (Response, error)

Get finds a global by its slug.

func (GlobalsServiceOp) Update

func (s GlobalsServiceOp) Update(ctx context.Context, global Global, in any, opts ...RequestOption) (Response, error)

Update updates a global by its slug.

type ListParams

type ListParams struct {
	Sort  string        `json:"sort" url:"sort"`   // Sort the returned documents by a specific field.
	Where *QueryBuilder `json:"where" url:"where"` // Constrain returned documents with a where query.
	Limit int           `json:"limit" url:"limit"` // Limit the returned documents to a certain number.
	Page  int           `json:"page" url:"page"`   // Get a specific page of documents.
}

ListParams represents additional query parameters for the find endpoint.

func (ListParams) Encode added in v0.0.5

func (p ListParams) Encode() string

Encode encodes ListParams into a URL query string.

type ListResponse

type ListResponse[T any] struct {
	Docs          []T  `json:"docs"`
	Total         int  `json:"total"`
	TotalDocs     int  `json:"totalDocs"`
	Limit         int  `json:"limit"`
	TotalPages    int  `json:"totalPages"`
	Page          int  `json:"page"`
	PagingCounter int  `json:"pagingCounter"`
	HasPrevPage   bool `json:"hasPrevPage"`
	HasNextPage   bool `json:"hasNextPage"`
	PrevPage      any  `json:"prevPage"`
	NextPage      any  `json:"nextPage"` //no:lint tagliatelle
}

ListResponse represents a list of entities that is sent back from the Payload CMS.

type MediaOptions

type MediaOptions struct {
	// The collection to upload the media to, defaults to "media"
	Collection Collection
	// Required filename for the upload, you do not need to pass the
	// extension here.
	// Note, this will not change the file extension.
	FileName string
}

MediaOptions represents non-required options for uploading media.

type MediaService

type MediaService interface {
	Upload(ctx context.Context, r io.Reader, in, out any, opts MediaOptions) (Response, error)
	UploadFromURL(ctx context.Context, url string, in, out any, opts MediaOptions) (Response, error)
}

MediaService is an interface for uploading media to the Payload API. Experimental feature.

See: https://payloadcms.com/docs/upload/overview

type MediaServiceOp

type MediaServiceOp struct {
	Client *Client
}

MediaServiceOp represents a service for managing media within Payload.

func (MediaServiceOp) Upload

func (s MediaServiceOp) Upload(ctx context.Context, r io.Reader, in, out any, opts MediaOptions) (Response, error)

Upload uploads a file to the media endpoint.

func (MediaServiceOp) UploadFromURL

func (s MediaServiceOp) UploadFromURL(ctx context.Context, url string, in, out any, opts MediaOptions) (Response, error)

type QueryBuilder added in v0.0.5

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

QueryBuilder represents the type for building Payload CMS where queries for Find/List routes.

See below for more info: https://payloadcms.com/docs/beta/queries/overview

func Query added in v0.0.5

func Query() *QueryBuilder

Query creates a new instance of QueryBuilder

func (*QueryBuilder) And added in v0.0.5

func (qb *QueryBuilder) And(subQuery *QueryBuilder) *QueryBuilder

And adds an AND condition to the query

func (*QueryBuilder) Build added in v0.0.5

func (qb *QueryBuilder) Build() string

Build constructs the final query string

func (*QueryBuilder) Equals added in v0.0.5

func (qb *QueryBuilder) Equals(field, value string) *QueryBuilder

Equals adds an equals filter to the query

func (*QueryBuilder) Exists added in v0.0.5

func (qb *QueryBuilder) Exists(field string, exists bool) *QueryBuilder

Exists adds an exists filter to the query

func (*QueryBuilder) GreaterThan added in v0.0.5

func (qb *QueryBuilder) GreaterThan(field, value string) *QueryBuilder

GreaterThan adds a greater_than filter to the query

func (*QueryBuilder) In added in v0.0.5

func (qb *QueryBuilder) In(field string, values []string) *QueryBuilder

In adds an in filter to the query

func (*QueryBuilder) LessThan added in v0.0.5

func (qb *QueryBuilder) LessThan(field, value string) *QueryBuilder

LessThan adds a less_than filter to the query

func (*QueryBuilder) NotEquals added in v0.0.5

func (qb *QueryBuilder) NotEquals(field, value string) *QueryBuilder

NotEquals adds a not_equals filter to the query

func (*QueryBuilder) Or added in v0.0.5

func (qb *QueryBuilder) Or(subQuery *QueryBuilder) *QueryBuilder

Or adds an OR condition to the query

type RequestOption added in v0.0.6

type RequestOption func(*http.Request)

RequestOption is a functional option type used to configure request options.

func WithDepth added in v0.0.6

func WithDepth(depth int) RequestOption

WithDepth sets the depth level for API responses. Depth determines how much nested data is included in the response.

See: https://payloadcms.com/docs/queries/depth

func WithQueryParam added in v0.0.6

func WithQueryParam(key, val string) RequestOption

WithQueryParam adds a query parameter to the API request.

type Response

type Response struct {
	*http.Response
	Content []byte `json:"-"`
	Message string `json:"-"`
	Errors  Errors `json:"errors"`
}

Response is a PayloadAPI API response. This wraps the standard http.Response returned from Payload and provides convenient access to things like body bytes.

type Service

type Service interface {
	Do(ctx context.Context, method, path string, body any, v any) (Response, error)
	DoWithRequest(ctx context.Context, req *http.Request, v any) (Response, error)
	Get(ctx context.Context, path string, v any) (Response, error)
	Post(ctx context.Context, path string, in any) (Response, error)
	Put(ctx context.Context, path string, in any) (Response, error)
	Delete(ctx context.Context, path string, v any) (Response, error)
}

Service is an interface that defines common methods for interacting with the Payload API.

See: https://payloadcms.com/docs/rest-api/overview

type UpdateResponse

type UpdateResponse[T any] struct {
	Doc     T      `json:"doc"`
	Message string `json:"message"`
	Errors  []any  `json:"error"`
}

UpdateResponse represents a response from the Payload CMS when an entity is updated.

Directories

Path Synopsis
Package payloadfakes provides mock implementations of various Payload CMS services.
Package payloadfakes provides mock implementations of various Payload CMS services.

Jump to

Keyboard shortcuts

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