From 8e9959abefbfc8553de1a87cdb4f2ba758085638 Mon Sep 17 00:00:00 2001 From: Giannis Katsanos Date: Fri, 9 Feb 2024 10:48:24 +0200 Subject: [PATCH] feat: Svix Webhooks API Added support for the Svix Webhooks API with Create, Delete and RefreshURL operations. --- clerk.go | 8 +++-- svix_webhook.go | 6 ++++ svixwebhook/api.go | 31 +++++++++++++++++++ svixwebhook/client.go | 52 +++++++++++++++++++++++++++++++ svixwebhook/client_test.go | 63 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 157 insertions(+), 3 deletions(-) create mode 100644 svix_webhook.go create mode 100644 svixwebhook/api.go create mode 100644 svixwebhook/client.go create mode 100644 svixwebhook/client_test.go diff --git a/clerk.go b/clerk.go index 1d48428..4b91a47 100644 --- a/clerk.go +++ b/clerk.go @@ -256,9 +256,11 @@ func (b *defaultBackend) do(req *http.Request, params Params, setter ResponseRea } setter.Read(apiResponse) - err = json.Unmarshal(resBody, setter) - if err != nil { - return err + if len(resBody) > 0 { + err := json.Unmarshal(resBody, setter) + if err != nil { + return err + } } return nil diff --git a/svix_webhook.go b/svix_webhook.go new file mode 100644 index 0000000..b95b3ec --- /dev/null +++ b/svix_webhook.go @@ -0,0 +1,6 @@ +package clerk + +type SvixWebhook struct { + APIResource + SvixURL string `json:"svix_url"` +} diff --git a/svixwebhook/api.go b/svixwebhook/api.go new file mode 100644 index 0000000..bd98291 --- /dev/null +++ b/svixwebhook/api.go @@ -0,0 +1,31 @@ +// Code generated by "gen"; DO NOT EDIT. +// This file is meant to be re-generated in place and/or deleted at any time. +// Last generated at 2024-02-09 08:48:20.100586445 +0000 UTC +package svixwebhook + +import ( + "context" + + "github.com/clerk/clerk-sdk-go/v2" +) + +// Create creates a Svix app. +func Create(ctx context.Context) (*clerk.SvixWebhook, error) { + return getClient().Create(ctx) +} + +// Delete deletes the Svix app. +func Delete(ctx context.Context) (*clerk.SvixWebhook, error) { + return getClient().Delete(ctx) +} + +// RefreshURL generates a new URL for accessing Svix's dashboard. +func RefreshURL(ctx context.Context) (*clerk.SvixWebhook, error) { + return getClient().RefreshURL(ctx) +} + +func getClient() *Client { + return &Client{ + Backend: clerk.GetBackend(), + } +} diff --git a/svixwebhook/client.go b/svixwebhook/client.go new file mode 100644 index 0000000..01182d4 --- /dev/null +++ b/svixwebhook/client.go @@ -0,0 +1,52 @@ +// Package svixwebhook provides the Svix Webhooks API. +package svixwebhook + +import ( + "context" + "net/http" + + "github.com/clerk/clerk-sdk-go/v2" +) + +//go:generate go run ../cmd/gen/main.go + +const path = "/webhooks/svix" + +// Client is used to invoke the Organizations API. +type Client struct { + Backend clerk.Backend +} + +type ClientConfig struct { + clerk.BackendConfig +} + +func NewClient(config *ClientConfig) *Client { + return &Client{ + Backend: clerk.NewBackend(&config.BackendConfig), + } +} + +// Create creates a Svix app. +func (c *Client) Create(ctx context.Context) (*clerk.SvixWebhook, error) { + req := clerk.NewAPIRequest(http.MethodPost, path) + resource := &clerk.SvixWebhook{} + err := c.Backend.Call(ctx, req, resource) + return resource, err +} + +// Delete deletes the Svix app. +func (c *Client) Delete(ctx context.Context) (*clerk.SvixWebhook, error) { + req := clerk.NewAPIRequest(http.MethodDelete, path) + resource := &clerk.SvixWebhook{} + err := c.Backend.Call(ctx, req, resource) + return resource, err +} + +// RefreshURL generates a new URL for accessing Svix's dashboard. +func (c *Client) RefreshURL(ctx context.Context) (*clerk.SvixWebhook, error) { + req := clerk.NewAPIRequest(http.MethodPost, "/webhooks/svix_url") + resource := &clerk.SvixWebhook{} + err := c.Backend.Call(ctx, req, resource) + return resource, err +} diff --git a/svixwebhook/client_test.go b/svixwebhook/client_test.go new file mode 100644 index 0000000..0545a1f --- /dev/null +++ b/svixwebhook/client_test.go @@ -0,0 +1,63 @@ +package svixwebhook + +import ( + "context" + "encoding/json" + "fmt" + "net/http" + "testing" + + "github.com/clerk/clerk-sdk-go/v2/clerktest" + "github.com/stretchr/testify/require" +) + +func TestSvixWebhookClientCreate(t *testing.T) { + t.Parallel() + svixURL := "https://foo.com/webhook" + config := &ClientConfig{} + config.HTTPClient = &http.Client{ + Transport: &clerktest.RoundTripper{ + T: t, + Out: json.RawMessage(fmt.Sprintf(`{"svix_url":"%s"}`, svixURL)), + Method: http.MethodPost, + Path: "/v1/webhooks/svix", + }, + } + client := NewClient(config) + webhook, err := client.Create(context.Background()) + require.NoError(t, err) + require.Equal(t, svixURL, webhook.SvixURL) +} + +func TestSvixWebhookClientDelete(t *testing.T) { + t.Parallel() + config := &ClientConfig{} + config.HTTPClient = &http.Client{ + Transport: &clerktest.RoundTripper{ + T: t, + Method: http.MethodDelete, + Path: "/v1/webhooks/svix", + }, + } + client := NewClient(config) + _, err := client.Delete(context.Background()) + require.NoError(t, err) +} + +func TestSvixWebhookClientRefreshURL(t *testing.T) { + t.Parallel() + svixURL := "https://foo.com/webhook" + config := &ClientConfig{} + config.HTTPClient = &http.Client{ + Transport: &clerktest.RoundTripper{ + T: t, + Out: json.RawMessage(fmt.Sprintf(`{"svix_url":"%s"}`, svixURL)), + Method: http.MethodPost, + Path: "/v1/webhooks/svix_url", + }, + } + client := NewClient(config) + webhook, err := client.RefreshURL(context.Background()) + require.NoError(t, err) + require.Equal(t, svixURL, webhook.SvixURL) +}