Skip to content

Commit 9fc8dd1

Browse files
committed
update campaigns create to match api changes
1 parent eb53b30 commit 9fc8dd1

6 files changed

Lines changed: 76 additions & 172 deletions

File tree

cmd/campaigns.go

Lines changed: 5 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -2,29 +2,23 @@ package cmd
22

33
import (
44
"fmt"
5-
"strings"
65

76
"github.com/loops-so/cli/internal/api"
87
"github.com/loops-so/cli/internal/config"
98
"github.com/spf13/cobra"
109
)
1110

12-
func fromEmailUsername(s string) string {
13-
before, _, _ := strings.Cut(s, "@")
14-
return before
15-
}
16-
1711
func runCampaignsGet(cfg *config.Config, id string) (*api.Campaign, error) {
1812
return newAPIClient(cfg).GetCampaign(id)
1913
}
2014

21-
func runCampaignsList(cfg *config.Config, params api.PaginationParams) ([]api.Campaign, error) {
15+
func runCampaignsList(cfg *config.Config, params api.PaginationParams) ([]api.CampaignListItem, error) {
2216
client := newAPIClient(cfg)
2317
if params.Cursor != "" {
2418
campaigns, _, err := client.ListCampaigns(params)
2519
return campaigns, err
2620
}
27-
return api.Paginate(func(cursor string) ([]api.Campaign, *api.Pagination, error) {
21+
return api.Paginate(func(cursor string) ([]api.CampaignListItem, *api.Pagination, error) {
2822
return client.ListCampaigns(api.PaginationParams{
2923
PerPage: params.PerPage,
3024
Cursor: cursor,
@@ -53,7 +47,7 @@ var campaignsListCmd = &cobra.Command{
5347

5448
if isJSONOutput() {
5549
if campaigns == nil {
56-
campaigns = []api.Campaign{}
50+
campaigns = []api.CampaignListItem{}
5751
}
5852
return printJSON(cmd.OutOrStdout(), campaigns)
5953
}
@@ -87,29 +81,13 @@ var campaignsCreateCmd = &cobra.Command{
8781
Short: "Create a draft campaign",
8882
RunE: func(cmd *cobra.Command, args []string) error {
8983
name, _ := cmd.Flags().GetString("name")
90-
params, err := emailMessageFieldParamsFromCmd(cmd)
91-
if err != nil {
92-
return err
93-
}
94-
95-
req := api.CreateCampaignRequest{Name: name}
96-
if len(params.Set) > 0 {
97-
req.EmailMessage = &api.EmailMessageFields{
98-
Subject: params.Subject,
99-
PreviewText: params.PreviewText,
100-
FromName: params.FromName,
101-
FromEmail: params.FromEmail,
102-
ReplyToEmail: params.ReplyToEmail,
103-
LMX: params.LMX,
104-
}
105-
}
10684

10785
cfg, err := loadConfig()
10886
if err != nil {
10987
return err
11088
}
11189

112-
resp, err := runCampaignsCreate(cfg, req)
90+
resp, err := runCampaignsCreate(cfg, api.CreateCampaignRequest{Name: name})
11391
if err != nil {
11492
return err
11593
}
@@ -118,24 +96,7 @@ var campaignsCreateCmd = &cobra.Command{
11896
return printJSON(cmd.OutOrStdout(), resp)
11997
}
12098

121-
emailMessageID := ""
122-
if resp.EmailMessage != nil {
123-
emailMessageID = resp.EmailMessage.EmailMessageID
124-
}
125-
fmt.Fprintf(cmd.OutOrStdout(), "Created. (id: %s, emailMessageId: %s)\n", resp.CampaignID, emailMessageID)
126-
127-
if len(resp.Warnings) > 0 {
128-
fmt.Fprintln(cmd.OutOrStdout())
129-
fmt.Fprintln(cmd.OutOrStdout(), "Warnings:")
130-
for _, warn := range resp.Warnings {
131-
if warn.Path != "" {
132-
fmt.Fprintf(cmd.OutOrStdout(), " [%s] %s (%s)\n", warn.Rule, warn.Message, warn.Path)
133-
} else {
134-
fmt.Fprintf(cmd.OutOrStdout(), " [%s] %s\n", warn.Rule, warn.Message)
135-
}
136-
}
137-
}
138-
99+
fmt.Fprintf(cmd.OutOrStdout(), "Created. (id: %s, emailMessageId: %s, contentRevisionId: %s)\n", resp.CampaignID, deref(resp.EmailMessageID), deref(resp.EmailMessageContentRevisionID))
139100
return nil
140101
},
141102
}
@@ -176,7 +137,6 @@ func init() {
176137
campaignsCmd.AddCommand(campaignsGetCmd)
177138

178139
campaignsCreateCmd.Flags().StringP("name", "n", "", "Campaign name (required)")
179-
addEmailMessageFieldFlags(campaignsCreateCmd)
180140
campaignsCreateCmd.MarkFlagRequired("name")
181141
campaignsCmd.AddCommand(campaignsCreateCmd)
182142

cmd/campaigns_create_test.go

Lines changed: 7 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -15,18 +15,8 @@ func TestRunCampaignsCreate(t *testing.T) {
1515
"status": "Draft",
1616
"createdAt": "2026-04-20T10:00:00Z",
1717
"updatedAt": "2026-04-20T10:00:00Z",
18-
"emailMessage": {
19-
"emailMessageId": "em_new",
20-
"campaignId": "cmp_new",
21-
"subject": "Hello",
22-
"previewText": "",
23-
"fromName": "",
24-
"fromEmail": "",
25-
"replyToEmail": "",
26-
"lmx": "",
27-
"contentRevisionId": "rev_1",
28-
"updatedAt": "2026-04-20T10:00:00Z"
29-
}
18+
"emailMessageId": "em_new",
19+
"emailMessageContentRevisionId": "rev_1"
3020
}`
3121

3222
t.Run("returns response on success", func(t *testing.T) {
@@ -38,8 +28,11 @@ func TestRunCampaignsCreate(t *testing.T) {
3828
if resp.CampaignID != "cmp_new" {
3929
t.Errorf("CampaignID = %q, want cmp_new", resp.CampaignID)
4030
}
41-
if resp.EmailMessage == nil || resp.EmailMessage.EmailMessageID != "em_new" {
42-
t.Errorf("EmailMessage = %v, want em_new", resp.EmailMessage)
31+
if deref(resp.EmailMessageID) != "em_new" {
32+
t.Errorf("EmailMessageID = %q, want em_new", deref(resp.EmailMessageID))
33+
}
34+
if deref(resp.EmailMessageContentRevisionID) != "rev_1" {
35+
t.Errorf("EmailMessageContentRevisionID = %q, want rev_1", deref(resp.EmailMessageContentRevisionID))
4336
}
4437
})
4538

@@ -51,23 +44,3 @@ func TestRunCampaignsCreate(t *testing.T) {
5144
}
5245
})
5346
}
54-
55-
func TestFromEmailUsername(t *testing.T) {
56-
tests := []struct {
57-
in string
58-
want string
59-
}{
60-
{"hello", "hello"},
61-
{"hello@acme.com", "hello"},
62-
{"hello@", "hello"},
63-
{"", ""},
64-
{"@acme.com", ""},
65-
}
66-
for _, tt := range tests {
67-
t.Run(tt.in, func(t *testing.T) {
68-
if got := fromEmailUsername(tt.in); got != tt.want {
69-
t.Errorf("fromEmailUsername(%q) = %q, want %q", tt.in, got, tt.want)
70-
}
71-
})
72-
}
73-
}

cmd/email_messages.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,18 @@ package cmd
33
import (
44
"fmt"
55
"os"
6+
"strings"
67

78
"github.com/loops-so/cli/internal/api"
89
"github.com/loops-so/cli/internal/config"
910
"github.com/spf13/cobra"
1011
)
1112

13+
func fromEmailUsername(s string) string {
14+
before, _, _ := strings.Cut(s, "@")
15+
return before
16+
}
17+
1218
// emailMessageFieldParams holds the six content fields shared by
1319
// `campaigns create` and `email-messages update`. Set records which fields the
1420
// user explicitly provided (keyed by JSON field name) so partial updates can

cmd/email_messages_update_test.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,26 @@ func TestRunEmailMessagesUpdate(t *testing.T) {
5757
})
5858
}
5959

60+
func TestFromEmailUsername(t *testing.T) {
61+
tests := []struct {
62+
in string
63+
want string
64+
}{
65+
{"hello", "hello"},
66+
{"hello@acme.com", "hello"},
67+
{"hello@", "hello"},
68+
{"", ""},
69+
{"@acme.com", ""},
70+
}
71+
for _, tt := range tests {
72+
t.Run(tt.in, func(t *testing.T) {
73+
if got := fromEmailUsername(tt.in); got != tt.want {
74+
t.Errorf("fromEmailUsername(%q) = %q, want %q", tt.in, got, tt.want)
75+
}
76+
})
77+
}
78+
}
79+
6080
func TestEmailMessageFieldParamsFromCmd(t *testing.T) {
6181
t.Run("unset flags are absent from Set", func(t *testing.T) {
6282
cmd := &cobra.Command{}

internal/api/campaigns.go

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,15 @@ import (
99
)
1010

1111
type Campaign struct {
12+
CampaignID string `json:"campaignId"`
13+
EmailMessageID *string `json:"emailMessageId"`
14+
Name string `json:"name"`
15+
Status string `json:"status"`
16+
CreatedAt string `json:"createdAt"`
17+
UpdatedAt string `json:"updatedAt"`
18+
}
19+
20+
type CampaignListItem struct {
1221
CampaignID string `json:"campaignId"`
1322
EmailMessageID *string `json:"emailMessageId"`
1423
Name string `json:"name"`
@@ -35,18 +44,12 @@ type EmailMessageFields struct {
3544
}
3645

3746
type CreateCampaignRequest struct {
38-
Name string `json:"name"`
39-
EmailMessage *EmailMessageFields `json:"emailMessage,omitempty"`
47+
Name string `json:"name"`
4048
}
4149

4250
type CampaignCreateResponse struct {
43-
CampaignID string `json:"campaignId"`
44-
Name string `json:"name"`
45-
Status string `json:"status"`
46-
CreatedAt string `json:"createdAt"`
47-
UpdatedAt string `json:"updatedAt"`
48-
EmailMessage *EmailMessage `json:"emailMessage,omitempty"`
49-
Warnings []LmxWarning `json:"warnings,omitempty"`
51+
Campaign
52+
EmailMessageContentRevisionID *string `json:"emailMessageContentRevisionId"`
5053
}
5154

5255
func (c *Client) CreateCampaign(req CreateCampaignRequest) (*CampaignCreateResponse, error) {
@@ -102,7 +105,7 @@ func (c *Client) GetCampaign(id string) (*Campaign, error) {
102105
return &result, nil
103106
}
104107

105-
func (c *Client) ListCampaigns(params PaginationParams) ([]Campaign, *Pagination, error) {
108+
func (c *Client) ListCampaigns(params PaginationParams) ([]CampaignListItem, *Pagination, error) {
106109
q := url.Values{}
107110
if params.PerPage != "" {
108111
q.Set("perPage", params.PerPage)
@@ -132,8 +135,8 @@ func (c *Client) ListCampaigns(params PaginationParams) ([]Campaign, *Pagination
132135
}
133136

134137
var result struct {
135-
Pagination Pagination `json:"pagination"`
136-
Data []Campaign `json:"data"`
138+
Pagination Pagination `json:"pagination"`
139+
Data []CampaignListItem `json:"data"`
137140
}
138141
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
139142
return nil, nil, fmt.Errorf("failed to decode response: %w", err)

0 commit comments

Comments
 (0)