Skip to content
This repository was archived by the owner on Mar 4, 2025. It is now read-only.

Commit ebe03f7

Browse files
Merge pull request #4 from roman-utila/roman/support-topics
feat: implement novu topics
2 parents 62f09f0 + e8d68f6 commit ebe03f7

File tree

8 files changed

+507
-17
lines changed

8 files changed

+507
-17
lines changed

lib/event.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ func (e *EventService) Trigger(ctx context.Context, eventId string, data ITrigge
3434
return resp, err
3535
}
3636

37-
err = e.client.sendRequest(req, &resp)
37+
_, err = e.client.sendRequest(req, &resp)
3838
if err != nil {
3939
return resp, err
4040
}

lib/event_test.go

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@ import (
44
"bytes"
55
"context"
66
"encoding/json"
7-
"github.com/novuhq/go-novu/lib"
8-
"github.com/stretchr/testify/require"
97
"io"
108
"io/ioutil"
119
"log"
@@ -15,6 +13,9 @@ import (
1513
"strings"
1614
"testing"
1715

16+
"github.com/novuhq/go-novu/lib"
17+
"github.com/stretchr/testify/require"
18+
1819
"github.com/stretchr/testify/assert"
1920
)
2021

@@ -78,3 +79,53 @@ func TestEventServiceTrigger_Success(t *testing.T) {
7879

7980
require.Nil(t, err)
8081
}
82+
83+
func TestEventServiceTriggerForTopic_Success(t *testing.T) {
84+
var (
85+
receivedBody lib.ITriggerPayloadOptions
86+
expectedTokenRequest lib.ITriggerPayloadOptions
87+
triggerPayload lib.ITriggerPayloadOptions
88+
)
89+
90+
eventService := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
91+
if err := json.NewDecoder(req.Body).Decode(&receivedBody); err != nil {
92+
log.Printf("error in unmarshalling %+v", err)
93+
w.WriteHeader(http.StatusBadRequest)
94+
return
95+
}
96+
97+
t.Run("Header must contain ApiKey", func(t *testing.T) {
98+
authKey := req.Header.Get("Authorization")
99+
assert.True(t, strings.Contains(authKey, novuApiKey))
100+
assert.True(t, strings.HasPrefix(authKey, "ApiKey"))
101+
})
102+
103+
t.Run("URL and request method is as expected", func(t *testing.T) {
104+
expectedURL := "/v1/events/trigger"
105+
assert.Equal(t, http.MethodPost, req.Method)
106+
assert.Equal(t, expectedURL, req.RequestURI)
107+
})
108+
109+
t.Run("Request is as expected", func(t *testing.T) {
110+
fileToStruct(filepath.Join("../testdata", "novu_send_trigger_topic_recipient.json"), &expectedTokenRequest)
111+
assert.Equal(t, expectedTokenRequest, receivedBody)
112+
})
113+
114+
var resp lib.EventResponse
115+
fileToStruct(filepath.Join("../testdata", "novu_send_trigger_response.json"), &resp)
116+
117+
w.WriteHeader(http.StatusOK)
118+
bb, _ := json.Marshal(resp)
119+
w.Write(bb)
120+
}))
121+
122+
defer eventService.Close()
123+
124+
ctx := context.Background()
125+
fileToStruct(filepath.Join("../testdata", "novu_send_trigger_topic_recipient.json"), &triggerPayload)
126+
127+
c := lib.NewAPIClient(novuApiKey, &lib.Config{BackendURL: eventService.URL})
128+
_, err := c.EventApi.Trigger(ctx, novuEventId, triggerPayload)
129+
130+
require.Nil(t, err)
131+
}

lib/model.go

Lines changed: 45 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,10 @@ type GeneralError error
88
const Version = "v1"
99

1010
const (
11-
HTTPStatusOk = 200
12-
HTTPStatusCreated = 201
13-
HTTPRedirectOk = 300
11+
HTTPStatusOk = 200
12+
HTTPStatusCreated = 201
13+
HTTPStatusNoChange = 204
14+
HTTPRedirectOk = 300
1415
)
1516

1617
const (
@@ -43,6 +44,11 @@ type TriggerRecipientsTypeSingle interface {
4344
string | SubscriberPayload
4445
}
4546

47+
type TriggerTopicRecipientsTypeSingle struct {
48+
TopicKey string `json:"topicKey,omitempty"`
49+
Type string `json:"type,omitempty"`
50+
}
51+
4652
type SubscriberPayload struct {
4753
FirstName string `json:"first_name,omitempty"`
4854
LastName string `json:"last_name,omitempty"`
@@ -53,7 +59,7 @@ type SubscriberPayload struct {
5359
}
5460

5561
type TriggerRecipientsType interface {
56-
TriggerRecipientsTypeSingle | TriggerRecipientsTypeArray
62+
TriggerRecipientsTypeSingle | TriggerRecipientsTypeArray | TriggerTopicRecipientsTypeSingle | []TriggerTopicRecipientsTypeSingle
5763
}
5864

5965
type ITriggerPayload interface {
@@ -83,3 +89,38 @@ type EventRequest struct {
8389
type SubscriberResponse struct {
8490
Data interface{} `json:"data"`
8591
}
92+
93+
type ListTopicsResponse struct {
94+
Page int `json:"name"`
95+
PageSize int `json:"pageSize"`
96+
TotalCount int `json:"totalCount"`
97+
Data []GetTopicResponse `json:"data"`
98+
}
99+
100+
type GetTopicResponse struct {
101+
Id string `json:"_id"`
102+
OrganizationId string `json:"_organizationId"`
103+
EnvironmentId string `json:"_environmentId"`
104+
Key string `json:"key"`
105+
Name string `json:"name"`
106+
Subscribers []string `json:"subscribers"`
107+
}
108+
109+
type ListTopicsOptions struct {
110+
Page *int `json:"page,omitempty"`
111+
PageSize *int `json:"pageSize,omitempty"`
112+
Key *string `json:"key,omitempty"`
113+
}
114+
115+
type CreateTopicRequest struct {
116+
Name string `json:"name"`
117+
Key string `json:"key"`
118+
}
119+
120+
type RenameTopicRequest struct {
121+
Name string `json:"name"`
122+
}
123+
124+
type SubscribersTopicRequest struct {
125+
Subscribers []string `json:"subscribers"`
126+
}

lib/novu.go

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,12 @@ package lib
33
import (
44
"encoding/json"
55
"fmt"
6-
"github.com/pkg/errors"
76
"io"
87
"net/http"
98
"strings"
109
"time"
10+
11+
"github.com/pkg/errors"
1112
)
1213

1314
type Config struct {
@@ -23,6 +24,7 @@ type APIClient struct {
2324
// Api Service
2425
SubscriberApi *SubscriberService
2526
EventApi *EventService
27+
TopicsApi *TopicService
2628
}
2729

2830
type service struct {
@@ -43,35 +45,41 @@ func NewAPIClient(apiKey string, cfg *Config) *APIClient {
4345
// API Services
4446
c.EventApi = (*EventService)(&c.common)
4547
c.SubscriberApi = (*SubscriberService)(&c.common)
48+
c.TopicsApi = (*TopicService)(&c.common)
4649

4750
return c
4851
}
4952

50-
func (c APIClient) sendRequest(req *http.Request, resp interface{}) error {
53+
func (c APIClient) sendRequest(req *http.Request, resp interface{}) (*http.Response, error) {
5154
req.Header.Set("Content-Type", "application/json")
5255
req.Header.Set("Authorization", fmt.Sprintf("ApiKey %s", c.apiKey))
5356

5457
res, err := c.config.HttpClient.Do(req)
5558
if err != nil {
56-
return errors.Wrap(err, "failed to execute request")
59+
return res, errors.Wrap(err, "failed to execute request")
5760
}
5861

5962
body, _ := io.ReadAll(res.Body)
6063
defer res.Body.Close()
6164

6265
if res.StatusCode >= http.StatusMultipleChoices {
63-
return errors.Errorf(
66+
return res, errors.Errorf(
6467
`request was not successful, status code %d, %s`, res.StatusCode,
6568
string(body),
6669
)
6770
}
6871

72+
if string(body) == "" {
73+
resp = map[string]string{}
74+
return res, nil
75+
}
76+
6977
err = c.decode(&resp, body)
7078
if err != nil {
71-
return errors.Wrap(err, "unable to unmarshal response body")
79+
return res, errors.Wrap(err, "unable to unmarshal response body")
7280
}
7381

74-
return nil
82+
return res, nil
7583
}
7684

7785
func (c APIClient) mergeStruct(target, patch interface{}) (interface{}, error) {

lib/subscribers.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@ import (
55
"context"
66
"encoding/json"
77
"fmt"
8-
"github.com/pkg/errors"
98
"net/http"
9+
10+
"github.com/pkg/errors"
1011
)
1112

1213
type ISubscribers interface {
@@ -33,7 +34,7 @@ func (s *SubscriberService) Identify(ctx context.Context, subscriberID string, d
3334
return resp, err
3435
}
3536

36-
err = s.client.sendRequest(req, &resp)
37+
_, err = s.client.sendRequest(req, &resp)
3738
if err != nil {
3839
return resp, err
3940
}
@@ -52,7 +53,7 @@ func (s *SubscriberService) Update(ctx context.Context, subscriberID string, dat
5253
return resp, err
5354
}
5455

55-
err = s.client.sendRequest(req, &resp)
56+
_, err = s.client.sendRequest(req, &resp)
5657
if err != nil {
5758
return resp, err
5859
}
@@ -69,7 +70,7 @@ func (s *SubscriberService) Delete(ctx context.Context, subscriberID string) (Su
6970
return resp, err
7071
}
7172

72-
err = s.client.sendRequest(req, &resp)
73+
_, err = s.client.sendRequest(req, &resp)
7374
if err != nil {
7475
return resp, err
7576
}

0 commit comments

Comments
 (0)