supabase

package module
v0.0.0-...-23ec39e Latest Latest
Warning

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

Go to latest
Published: May 27, 2026 License: MIT Imports: 22 Imported by: 0

README

supabase-go

Unofficial Supabase client for Go. It is an amalgamation of all the libraries similar to the official Supabase client.

Installation

go get github.com/semvis123/supabase-go

Usage

Replace the <SUPABASE-URL> and <SUPABASE-URL> placeholders with values from https://supabase.com/dashboard/project/YOUR_PROJECT/settings/api

Authenticate
package main
import (
    supa "github.com/semvis123/supabase-go"
    "fmt"
    "context"
)

func main() {
  supabaseUrl := "<SUPABASE-URL>"
  supabaseKey := "<SUPABASE-KEY>"
  supabase := supa.CreateClient(supabaseUrl, supabaseKey)

  ctx := context.Background()
  user, err := supabase.Auth.SignUp(ctx, supa.UserCredentials{
    Email:    "example@example.com",
    Password: "password",
  })
  if err != nil {
    panic(err)
  }

  fmt.Println(user)
}
Sign-In
package main
import (
    supa "github.com/semvis123/supabase-go"
    "fmt"
    "context"
)

func main() {
  supabaseUrl := "<SUPABASE-URL>"
  supabaseKey := "<SUPABASE-KEY>"
  supabase := supa.CreateClient(supabaseUrl, supabaseKey)

  ctx := context.Background()
  user, err := supabase.Auth.SignIn(ctx, supa.UserCredentials{
    Email:    "example@example.com",
    Password: "password",
  })
  if err != nil {
    panic(err)
  }

  fmt.Println(user)
}
Insert
package main
import (
    supa "github.com/semvis123/supabase-go"
    "fmt"
)

type Country struct {
  ID      int    `json:"id"`
  Name    string `json:"name"`
  Capital string `json:"capital"`
}

func main() {
  supabaseUrl := "<SUPABASE-URL>"
  supabaseKey := "<SUPABASE-KEY>"
  supabase := supa.CreateClient(supabaseUrl, supabaseKey)

  row := Country{
    ID:      5,
    Name:    "Germany",
    Capital: "Berlin",
  }

  var results []Country
  err := supabase.DB.From("countries").Insert(row).Execute(&results)
  if err != nil {
    panic(err)
  }

  fmt.Println(results) // Inserted rows
}
Select
package main
import (
    supa "github.com/semvis123/supabase-go"
    "fmt"
)

func main() {
  supabaseUrl := "<SUPABASE-URL>"
  supabaseKey := "<SUPABASE-KEY>"
  supabase := supa.CreateClient(supabaseUrl, supabaseKey)

  var results map[string]interface{}
  err := supabase.DB.From("countries").Select("*").Single().Execute(&results)
  if err != nil {
    panic(err)
  }

  fmt.Println(results) // Selected rows
}
Update
package main
import (
    supa "github.com/semvis123/supabase-go"
    "fmt"
)

type Country struct {
  Name    string `json:"name"`
  Capital string `json:"capital"`
}

func main() {
  supabaseUrl := "<SUPABASE-URL>"
  supabaseKey := "<SUPABASE-KEY>"
  supabase := supa.CreateClient(supabaseUrl, supabaseKey)

  row := Country{
    Name:    "France",
    Capital: "Paris",
  }

  var results map[string]interface{}
  err := supabase.DB.From("countries").Update(row).Eq("id", "5").Execute(&results)
  if err != nil {
    panic(err)
  }

  fmt.Println(results) // Updated rows
}
Delete
package main
import (
    supa "github.com/semvis123/supabase-go"
    "fmt"
)

func main() {
  supabaseUrl := "<SUPABASE-URL>"
  supabaseKey := "<SUPABASE-KEY>"
  supabase := supa.CreateClient(supabaseUrl, supabaseKey)

  var results map[string]interface{}
  err := supabase.DB.From("countries").Delete().Eq("name", "France").Execute(&results)
  if err != nil {
    panic(err)
  }

  fmt.Println(results) // Empty - nothing returned from delete
}
Invite user by email
package main
import (
    supa "github.com/semvis123/supabase-go"
    "fmt"
    "context"
)

func main() {
  supabaseUrl := "<SUPABASE-URL>"
  supabaseKey := "<SUPABASE-KEY>"
  supabase := supa.CreateClient(supabaseUrl, supabaseKey)

  ctx := context.Background()
  user, err := supabase.Auth.InviteUserByEmail(ctx, email)
  if err != nil {
    panic(err)
  }

  // or if you want to setup some metadata
  data := map[string]interface{}{ "invitedBy": "someone" }
  redirectTo := "https://your_very_successful_app.com/signup"
  user, err = supabase.Auth.InviteUserByEmailWithData(ctx, email, data, redirectTo)
  if err != nil {
    panic(err)
  }

  fmt.Println(user)
}

Roadmap

  • Auth support (1)
  • DB support (2)
  • Realtime (WIP)
  • Storage
  • Testing

(1) - Thin API wrapper. Does not rely on the GoTrue library for simplicity (2) - Through postgrest-go

I just implemented features which I actually needed for my project for now. If you like to implement these features, feel free to submit a pull request as stated in the Contributing section below.

Design Goals

It tries to mimick as much as possible the official Javascript client library in terms of ease-of-use and in setup process.

Contributing

Submitting a pull request

  • Fork it (https://github.com/semvis123/supabase-go/fork)
  • Create your feature branch (git checkout -b my-new-feature)
  • Commit your changes (git commit -am 'Add some feature')
  • Push to the branch (git push origin my-new-feature)
  • Create a new Pull Request

Contributors

Documentation

Index

Constants

View Source
const (
	AuthEndpoint     = "auth/v1"
	AdminEndpoint    = "auth/v1/admin"
	RestEndpoint     = "rest/v1"
	StorageEndpoint  = "storage/v1"
	RealtimeEndpoint = "realtime/v1"
)

Variables

View Source
var ErrNotFound = errors.New("file not found")

Functions

This section is empty.

Types

type Admin

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

func (*Admin) CreateUser

func (a *Admin) CreateUser(ctx context.Context, params AdminUserParams) (*AdminUser, error)

Create a user

func (a *Admin) GenerateLink(ctx context.Context, params GenerateLinkParams) (*GenerateLinkResponse, error)

Update a user

func (*Admin) GetUser

func (a *Admin) GetUser(ctx context.Context, userID string) (*AdminUser, error)

Retrieve the user

func (*Admin) UpdateUser

func (a *Admin) UpdateUser(ctx context.Context, userID string, params AdminUserParams) (*AdminUser, error)

Update a user

type AdminUser

type AdminUser struct {
	ID string `json:"id" db:"id"`

	Aud   string `json:"aud" db:"aud"`
	Role  string `json:"role" db:"role"`
	Email string `json:"email" db:"email"`

	EmailConfirmedAt *time.Time `json:"email_confirmed_at,omitempty" db:"email_confirmed_at"`
	InvitedAt        *time.Time `json:"invited_at,omitempty" db:"invited_at"`

	Phone            string     `json:"phone" db:"phone"`
	PhoneConfirmedAt *time.Time `json:"phone_confirmed_at,omitempty" db:"phone_confirmed_at"`

	ConfirmationSentAt *time.Time `json:"confirmation_sent_at,omitempty" db:"confirmation_sent_at"`

	RecoverySentAt *time.Time `json:"recovery_sent_at,omitempty" db:"recovery_sent_at"`

	EmailChange       string     `json:"new_email,omitempty" db:"email_change"`
	EmailChangeSentAt *time.Time `json:"email_change_sent_at,omitempty" db:"email_change_sent_at"`

	PhoneChange       string     `json:"new_phone,omitempty" db:"phone_change"`
	PhoneChangeSentAt *time.Time `json:"phone_change_sent_at,omitempty" db:"phone_change_sent_at"`

	ReauthenticationSentAt *time.Time `json:"reauthentication_sent_at,omitempty" db:"reauthentication_sent_at"`

	LastSignInAt *time.Time `json:"last_sign_in_at,omitempty" db:"last_sign_in_at"`

	AppMetaData  JSONMap `json:"app_metadata" db:"raw_app_meta_data"`
	UserMetaData JSONMap `json:"user_metadata" db:"raw_user_meta_data"`

	Factors    []Factor   `json:"factors,omitempty" has_many:"factors"`
	Identities []Identity `json:"identities" has_many:"identities"`

	CreatedAt   time.Time  `json:"created_at" db:"created_at"`
	UpdatedAt   time.Time  `json:"updated_at" db:"updated_at"`
	BannedUntil *time.Time `json:"banned_until,omitempty" db:"banned_until"`
	DeletedAt   *time.Time `json:"deleted_at,omitempty" db:"deleted_at"`
}

type AdminUserParams

type AdminUserParams struct {
	Role         string  `json:"role"`
	Email        string  `json:"email"`
	Phone        string  `json:"phone"`
	Password     *string `json:"password"`
	EmailConfirm bool    `json:"email_confirm"`
	PhoneConfirm bool    `json:"phone_confirm"`
	UserMetadata JSONMap `json:"user_metadata"`
	AppMetadata  JSONMap `json:"app_metadata"`
	BanDuration  string  `json:"ban_duration"`
}

type Auth

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

func (*Auth) ExchangeCode

func (a *Auth) ExchangeCode(ctx context.Context, opts ExchangeCodeOpts) (*AuthenticatedDetails, error)

ExchangeCode takes an auth code and PCKE verifier and returns the current user if succeeded.

func (*Auth) InviteUserByEmail

func (a *Auth) InviteUserByEmail(ctx context.Context, email string) (*User, error)

InviteUserByEmail sends an invite link to the given email. Returns a user.

func (*Auth) InviteUserByEmailWithData

func (a *Auth) InviteUserByEmailWithData(ctx context.Context, email string, data map[string]interface{}, redirectTo string) (*User, error)

InviteUserByEmailWithOpts sends an invite link to the given email with metadata. Returns a user.

func (*Auth) RefreshUser

func (a *Auth) RefreshUser(ctx context.Context, userToken string, refreshToken string) (*AuthenticatedDetails, error)

SignIn enters the user credentials and returns the current user if succeeded.

func (*Auth) ResetPasswordForEmail

func (a *Auth) ResetPasswordForEmail(ctx context.Context, email string) error

ResetPasswordForEmail sends a password recovery link to the given e-mail address.

func (a *Auth) SendMagicLink(ctx context.Context, email string) error

SendMagicLink sends a link to a specific e-mail address for passwordless auth.

func (*Auth) SignIn

func (a *Auth) SignIn(ctx context.Context, credentials UserCredentials) (*AuthenticatedDetails, error)

SignIn enters the user credentials and returns the current user if succeeded.

func (*Auth) SignInWithProvider

func (a *Auth) SignInWithProvider(opts ProviderSignInOptions) (*ProviderSignInDetails, error)

SignInWithProvider returns a URL for signing in via OAuth

func (*Auth) SignOut

func (a *Auth) SignOut(ctx context.Context, userToken string) error

SignOut revokes the users token and session.

func (*Auth) SignUp

func (a *Auth) SignUp(ctx context.Context, credentials UserCredentials) (*User, error)

SignUp registers the user's email and password to the database.

func (*Auth) UpdateUser

func (a *Auth) UpdateUser(ctx context.Context, userToken string, updateData map[string]interface{}) (*User, error)

UpdateUser updates the user information

func (*Auth) User

func (a *Auth) User(ctx context.Context, userToken string) (*User, error)

User retrieves the user information based on the given token

type AuthenticatedDetails

type AuthenticatedDetails struct {
	AccessToken          string `json:"access_token"`
	TokenType            string `json:"token_type"`
	ExpiresIn            int    `json:"expires_in"`
	RefreshToken         string `json:"refresh_token"`
	User                 User   `json:"user"`
	ProviderToken        string `json:"provider_token"`
	ProviderRefreshToken string `json:"provider_refresh_token"`
}

type BucketOption

type BucketOption struct {
	Id     string `json:"id"`
	Name   string `json:"name"`
	Public bool   `json:"public"`
}

type Channel

type Channel struct {
	Topic  string
	Url    string
	Origin string

	OnDisconnect func(*Channel)
	OnConnect    func(*Channel)
	// contains filtered or unexported fields
}

Channel represents a realtime channel.

All exported fields (Topic, Url, Origin, OnConnect, OnDisconnect) must be set before Listen() or the first Send() and treated as read-only after; they are read from internal goroutines without synchronization.

OnConnect and OnDisconnect are invoked from internal goroutines, so they may call Close() without deadlocking. They are not serialized with each other — a slow OnConnect can overlap with the next OnDisconnect, and in rare races (Close() arriving just as a connect goroutine is being launched) you may observe an OnDisconnect with no preceding OnConnect. Listener callbacks registered with On(...) run synchronously on the read goroutine and MUST NOT call Close().

func (*Channel) Close

func (c *Channel) Close()

Close terminates the channel. Subsequent reconnect signals are ignored, keepAlive (if running) exits, the websocket is closed, and further Send calls return errChannelClosed. Safe to call more than once. On return c.connected is false and c.ws is closed regardless of whether Listen() was called.

Close does not wait for the read goroutine or for OnConnect/OnDisconnect callback goroutines, which is what makes it safe to call from those callbacks.

func (*Channel) IsConnected

func (c *Channel) IsConnected() bool

IsConnected reports whether the channel currently believes it has an open websocket. It is a snapshot — by the time the caller acts on it, the channel may have disconnected.

func (*Channel) Listen

func (c *Channel) Listen() error

Listen connects the channel and starts the keepAlive loop. It must be called at most once per channel; calling it twice would spawn two keepAlive goroutines, doubling heartbeats and racing on shutdown. If Listen returns an error, the channel can be retried (started is reset).

func (*Channel) On

func (c *Channel) On(event string, callback func(*Channel, *Message))

func (*Channel) RemoveCallbacksForEvent

func (c *Channel) RemoveCallbacksForEvent(event string)

func (*Channel) Send

func (c *Channel) Send(event string, payload map[string]interface{}) error

Send transmits an event, opening the connection on first use. Without a prior Listen() the channel does not auto-reconnect: a dropped connection is reopened lazily on the next Send().

type Client

type Client struct {
	BaseURL string

	Headers    map[string]string
	HTTPClient *http.Client
	Admin      *Admin
	Auth       *Auth
	Storage    *Storage
	Realtime   *Realtime
	DB         *postgrest.Client
	// contains filtered or unexported fields
}

func CreateClient

func CreateClient(baseURL string, supabaseKey string, debug ...bool) *Client

CreateClient creates a new Supabase client

func CreateClientWithHeaders

func CreateClientWithHeaders(baseURL string, supabaseKey string, headers map[string]string, debug ...bool) *Client

CreateClient creates a new Supabase client

type ErrorResponse

type ErrorResponse struct {
	Code    int    `json:"code"`
	Message string `json:"msg"`
}

func (*ErrorResponse) Error

func (err *ErrorResponse) Error() string

type ExchangeCodeOpts

type ExchangeCodeOpts struct {
	AuthCode     string `json:"auth_code"`
	CodeVerifier string `json:"code_verifier"`
}

type Factor

type Factor struct {
	ID           string    `json:"id" db:"id"`
	CreatedAt    time.Time `json:"created_at" db:"created_at"`
	UpdatedAt    time.Time `json:"updated_at" db:"updated_at"`
	Status       string    `json:"status" db:"status"`
	FriendlyName string    `json:"friendly_name,omitempty" db:"friendly_name"`
	FactorType   string    `json:"factor_type" db:"factor_type"`
}

type FileErrorResponse

type FileErrorResponse struct {
	Status     string `json:"statusCode"`
	ShortError string `json:"error"`
	Message    string `json:"message"`
}

func (*FileErrorResponse) Error

func (err *FileErrorResponse) Error() string

type FileObject

type FileObject struct {
	Name           string      `json:"name"`
	BucketId       string      `json:"bucket_id"`
	Owner          string      `json:"owner"`
	Id             string      `json:"id"`
	UpdatedAt      string      `json:"updated_at"`
	CreatedAt      string      `json:"created_at"`
	LastAccessedAt string      `json:"last_accessed_at"`
	Metadata       interface{} `json:"metadata"`
	Buckets        bucket      `json:"buckets"`
}

type FileResponse

type FileResponse struct {
	Key     string `json:"key"`
	Message string `json:"message"`
}

type FileSearchOptions

type FileSearchOptions struct {
	Limit  int    `json:"limit"`
	Offset int    `json:"offset"`
	SortBy SortBy `json:"sortBy"`
}

type FileUploadOptions

type FileUploadOptions struct {
	CacheControl string
	ContentType  string
	Upsert       bool
}

type FlowType

type FlowType string
const (
	Implicit FlowType = "implicit"
	PKCE     FlowType = "pkce"
)

type GenerateLinkParams

type GenerateLinkParams struct {
	Type       string                 `json:"type"`
	Email      string                 `json:"email"`
	NewEmail   string                 `json:"new_email"`
	Password   string                 `json:"password"`
	Data       map[string]interface{} `json:"data"`
	RedirectTo string                 `json:"redirect_to"`
}

type GenerateLinkResponse

type GenerateLinkResponse struct {
	AdminUser
	ActionLink       string `json:"action_link"`
	EmailOtp         string `json:"email_otp"`
	HashedToken      string `json:"hashed_token"`
	VerificationType string `json:"verification_type"`
	RedirectTo       string `json:"redirect_to"`
}

type Identity

type Identity struct {
	ID           string     `json:"id" db:"id"`
	UserID       string     `json:"user_id" db:"user_id"`
	IdentityData JSONMap    `json:"identity_data,omitempty" db:"identity_data"`
	Provider     string     `json:"provider" db:"provider"`
	LastSignInAt *time.Time `json:"last_sign_in_at,omitempty" db:"last_sign_in_at"`
	CreatedAt    time.Time  `json:"created_at" db:"created_at"`
	UpdatedAt    time.Time  `json:"updated_at" db:"updated_at"`
}

type JSONMap

type JSONMap map[string]interface{}

type ListFileRequest

type ListFileRequest struct {
	Limit  int    `json:"limit"`
	Offset int    `json:"offset"`
	SortBy SortBy `json:"sortBy"`
	Prefix string `json:"prefix"`
}

type Listener

type Listener struct {
	EventName string
	// contains filtered or unexported fields
}

type Message

type Message struct {
	Event   string                 `json:"event"`
	Payload map[string]interface{} `json:"payload"`
	Ref     *string                `json:"ref"`
	Topic   string                 `json:"topic"`
}

type PKCEParams

type PKCEParams struct {
	Challenge       string
	ChallengeMethod string
	Verifier        string
}

adapted from https://go-review.googlesource.com/c/oauth2/+/463979/9/pkce.go#64

type ProviderSignInDetails

type ProviderSignInDetails struct {
	URL          string `json:"url"`
	Provider     string `json:"provider"`
	CodeVerifier string `json:"code_verifier"`
}

type ProviderSignInOptions

type ProviderSignInOptions struct {
	Provider   string   `url:"provider"`
	RedirectTo string   `url:"redirect_to"`
	Scopes     []string `url:"scopes"`
	FlowType   FlowType
}

type Realtime

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

func (*Realtime) Channel

func (r *Realtime) Channel(topic string) *Channel

func (*Realtime) ChannelWithUrl

func (r *Realtime) ChannelWithUrl(topic string, websocketUrl string) *Channel

type SignedUrlResponse

type SignedUrlResponse struct {
	SignedUrl string `json:"signedURL"`
}

type SortBy

type SortBy struct {
	Column string `json:"column"`
	Order  string `json:"order"`
}

type Storage

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

func (*Storage) CreateBucket

func (s *Storage) CreateBucket(ctx context.Context, option BucketOption) (*bucket, error)

CreateBucket creates a new storage bucket @param: option: a bucketOption with the name and id of the bucket you want to create @returns: bucket: a response with the details of the bucket of the bucket created

func (*Storage) DeleteBucket

func (s *Storage) DeleteBucket(ctx context.Context, id string) (*bucketResponse, error)

DeleteBucket deletes a bucket by its id, a bucket can't be deleted except emptied @param: id: the id of the bucket @returns bucketMessage: a successful response message or failed

func (*Storage) EmptyBucket

func (s *Storage) EmptyBucket(ctx context.Context, id string) (*bucketMessage, error)

EmptyBucket empties the object of a bucket by id @param: id: the id of the bucket @returns bucketMessage: a successful response message or failed

func (*Storage) From

func (s *Storage) From(bucketId string) *file

func (*Storage) GetBucket

func (s *Storage) GetBucket(ctx context.Context, id string) (*bucketResponse, error)

GetBucket retrieves a bucket by its id @param: id: the id of the bucket @returns: bucketResponse: a response with the details of the bucket

func (*Storage) ListBuckets

func (s *Storage) ListBuckets(ctx context.Context) (*[]bucketResponse, error)

ListBucket retrieves all buckets ina supabase storage @returns: []bucketResponse: a response with the details of all the bucket

func (*Storage) UpdateBucket

func (s *Storage) UpdateBucket(ctx context.Context, id string, option BucketOption) (*bucketMessage, error)

UpdateBucket updates a bucket by its id @param: id: the id of the bucket @param: option: the options to be updated @returns bucketMessage: a successful response message or failed

type User

type User struct {
	ID                 string    `json:"id"`
	Aud                string    `json:"aud"`
	Role               string    `json:"role"`
	Email              string    `json:"email"`
	InvitedAt          time.Time `json:"invited_at"`
	ConfirmedAt        time.Time `json:"confirmed_at"`
	ConfirmationSentAt time.Time `json:"confirmation_sent_at"`
	AppMetadata        struct {
		// contains filtered or unexported fields
	} `json:"app_metadata"`
	UserMetadata map[string]interface{} `json:"user_metadata"`
	CreatedAt    time.Time              `json:"created_at"`
	UpdatedAt    time.Time              `json:"updated_at"`
}

type UserCredentials

type UserCredentials struct {
	Email    string
	Password string
	Data     interface{}
}

Jump to

Keyboard shortcuts

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