Skip to content

Commit 5b21c7d

Browse files
authored
chore: openapi spec 1.21.6 (#18)
1 parent 80987c7 commit 5b21c7d

3 files changed

Lines changed: 275 additions & 22 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ client := loops.NewClient("YOUR_API_KEY",
6565
- Components — `GetComponent`, `ListComponents`, `CreateComponent`, `UpdateComponent`
6666
- Themes — `GetTheme`, `ListThemes`, `CreateTheme`, `UpdateTheme`
6767
- Uploads — `Upload`, `CreateUpload`, `CompleteUpload`
68-
- Workflows — `ListWorkflows`, `GetWorkflow`, `GetWorkflowNode`, `CreateWorkflow`, `UpdateWorkflow`, `ChangeWorkflowMailingList`, `CreateWorkflowNode`, `UpdateWorkflowNode`, `AddWorkflowBranch`, `DeleteWorkflowNode`, `DeleteWorkflowNodeRecursive`
68+
- Workflows — `ListWorkflows`, `GetWorkflow`, `GetWorkflowNode`, `CreateWorkflow`, `UpdateWorkflow`, `ChangeWorkflowMailingList`, `CreateWorkflowNode`, `UpdateWorkflowNode`, `AddWorkflowBranch`, `RerouteNodeConnection`, `DeleteWorkflowNode`, `DeleteWorkflowNodeRecursive`
6969

7070
Full reference: [pkg.go.dev/github.com/loops-so/loops-go](https://pkg.go.dev/github.com/loops-so/loops-go).
7171

workflows.go

Lines changed: 134 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1255,13 +1255,14 @@ type ChangeWorkflowMailingListRequest struct {
12551255

12561256
// ChangeWorkflowMailingListResponse is returned by
12571257
// [Client.ChangeWorkflowMailingList]. Status is one of the
1258-
// WorkflowMutationStatus* values. WorkflowRevisionID is set only when Status
1259-
// is "updated".
1258+
// WorkflowMutationStatus* values. WorkflowRevisionID and Workflow are set only
1259+
// when Status is "updated".
12601260
type ChangeWorkflowMailingListResponse struct {
1261-
Status string `json:"status"`
1262-
MailingListID *string `json:"mailingListId"`
1263-
WorkflowRevisionID *string `json:"workflowRevisionId,omitempty"`
1264-
QueuedContactCount float64 `json:"queuedContactCount"`
1261+
Status string `json:"status"`
1262+
MailingListID *string `json:"mailingListId"`
1263+
WorkflowRevisionID *string `json:"workflowRevisionId,omitempty"`
1264+
QueuedContactCount float64 `json:"queuedContactCount"`
1265+
Workflow *SimplifiedWorkflow `json:"workflow,omitempty"`
12651266
}
12661267

12671268
// ChangeWorkflowMailingList changes the mailing list of the workflow
@@ -1312,6 +1313,7 @@ func (c *Client) ChangeWorkflowMailingList(id string, req ChangeWorkflowMailingL
13121313
const (
13131314
WorkflowInsertModeBetween = "between"
13141315
WorkflowInsertModeBefore = "before"
1316+
WorkflowInsertModeAfter = "after"
13151317
)
13161318

13171319
// Node types that can be created via [Client.CreateWorkflowNode]. Trigger and
@@ -1329,8 +1331,11 @@ const (
13291331
// InsertMode selects the placement:
13301332
// - "between" inserts between FromNodeID and ToNodeID (FromNodeID must
13311333
// currently point to ToNodeID); both are required.
1332-
// - "before" inserts before BeforeNodeID, which must have an incoming parent
1333-
// and cannot be a trigger node.
1334+
// - "before" inserts before ToNodeID, which must have an incoming parent and
1335+
// cannot be a trigger node.
1336+
// - "after" inserts after FromNodeID, valid only when FromNodeID has exactly
1337+
// one outgoing node (not zero, not multiple, and not an exit node). Use
1338+
// "between" with an explicit ToNodeID when the source has multiple outputs.
13341339
//
13351340
// ExpectedRevisionID is required and always sent (as JSON null when nil).
13361341
// NodeTypeName is one of the CreateWorkflowNodeType* constants.
@@ -1340,7 +1345,10 @@ type CreateWorkflowNodeRequest struct {
13401345
NodeTypeName string
13411346
FromNodeID string
13421347
ToNodeID string
1343-
BeforeNodeID string
1348+
1349+
// Deprecated: the API now expects ToNodeID for "before" mode. Set ToNodeID
1350+
// instead; BeforeNodeID is only sent when ToNodeID is empty.
1351+
BeforeNodeID string
13441352
}
13451353

13461354
// CreateWorkflowNodeResponse is returned by [Client.CreateWorkflowNode].
@@ -1363,7 +1371,13 @@ func (c *Client) CreateWorkflowNode(id string, req CreateWorkflowNodeRequest) (*
13631371
body["fromNodeId"] = req.FromNodeID
13641372
body["toNodeId"] = req.ToNodeID
13651373
case WorkflowInsertModeBefore:
1366-
body["beforeNodeId"] = req.BeforeNodeID
1374+
if req.ToNodeID != "" {
1375+
body["toNodeId"] = req.ToNodeID
1376+
} else {
1377+
body["beforeNodeId"] = req.BeforeNodeID
1378+
}
1379+
case WorkflowInsertModeAfter:
1380+
body["fromNodeId"] = req.FromNodeID
13671381
}
13681382

13691383
b, err := json.Marshal(body)
@@ -1508,8 +1522,33 @@ type UpdateWorkflowNodeRequest struct {
15081522
}
15091523

15101524
// UpdateWorkflowNodeResponse is the updated node returned by
1511-
// [Client.UpdateWorkflowNode], with the latest workflow revision token.
1512-
type UpdateWorkflowNodeResponse = WorkflowMutationNodeWithRevision
1525+
// [Client.UpdateWorkflowNode] (its fields stay flat via the embedded type)
1526+
// plus the latest simplified workflow.
1527+
type UpdateWorkflowNodeResponse struct {
1528+
WorkflowMutationNodeWithRevision
1529+
Workflow SimplifiedWorkflow `json:"workflow"`
1530+
}
1531+
1532+
// UnmarshalJSON decodes the node and revision via the embedded type and then
1533+
// the latest workflow.
1534+
func (n *UpdateWorkflowNodeResponse) UnmarshalJSON(data []byte) error {
1535+
if err := n.WorkflowMutationNodeWithRevision.UnmarshalJSON(data); err != nil {
1536+
return err
1537+
}
1538+
var extra struct {
1539+
Workflow SimplifiedWorkflow `json:"workflow"`
1540+
}
1541+
if err := json.Unmarshal(data, &extra); err != nil {
1542+
return err
1543+
}
1544+
n.Workflow = extra.Workflow
1545+
return nil
1546+
}
1547+
1548+
// MarshalJSON encodes the embedded node and revision and adds the workflow.
1549+
func (n UpdateWorkflowNodeResponse) MarshalJSON() ([]byte, error) {
1550+
return mergeMarshal(n.WorkflowMutationNodeWithRevision, map[string]any{"workflow": n.Workflow})
1551+
}
15131552

15141553
// UpdateWorkflowNode applies req.Payload to the node identified by
15151554
// workflowID/nodeID and returns the updated node.
@@ -1606,13 +1645,14 @@ type DeleteWorkflowNodeRequest struct {
16061645

16071646
// DeleteWorkflowNodeResponse is returned by [Client.DeleteWorkflowNode] and
16081647
// [Client.DeleteWorkflowNodeRecursive]. Status is one of the
1609-
// WorkflowMutationStatus* values. WorkflowRevisionID is set only when Status
1610-
// is "deleted".
1648+
// WorkflowMutationStatus* values. WorkflowRevisionID and Workflow are set only
1649+
// when Status is "deleted".
16111650
type DeleteWorkflowNodeResponse struct {
1612-
Status string `json:"status"`
1613-
NodeIDs []string `json:"nodeIds"`
1614-
WorkflowRevisionID *string `json:"workflowRevisionId,omitempty"`
1615-
QueuedContactCount float64 `json:"queuedContactCount"`
1651+
Status string `json:"status"`
1652+
NodeIDs []string `json:"nodeIds"`
1653+
WorkflowRevisionID *string `json:"workflowRevisionId,omitempty"`
1654+
QueuedContactCount float64 `json:"queuedContactCount"`
1655+
Workflow *SimplifiedWorkflow `json:"workflow,omitempty"`
16161656
}
16171657

16181658
func (c *Client) deleteWorkflowNode(path string, req DeleteWorkflowNodeRequest) (*DeleteWorkflowNodeResponse, error) {
@@ -1667,3 +1707,79 @@ func (c *Client) DeleteWorkflowNode(workflowID, nodeID string, req DeleteWorkflo
16671707
func (c *Client) DeleteWorkflowNodeRecursive(workflowID, nodeID string, req DeleteWorkflowNodeRequest) (*DeleteWorkflowNodeResponse, error) {
16681708
return c.deleteWorkflowNode("/workflows/"+workflowID+"/nodes/"+nodeID+"/recursive", req)
16691709
}
1710+
1711+
// RerouteNodeConnectionRequest is the request body for
1712+
// [Client.RerouteNodeConnection]. ExpectedRevisionID is required and always
1713+
// sent (as JSON null when nil). NewTargetNodeID is the valid node that should
1714+
// receive the source node's outgoing connection.
1715+
type RerouteNodeConnectionRequest struct {
1716+
ExpectedRevisionID *string
1717+
NewTargetNodeID string
1718+
}
1719+
1720+
// RerouteNodeConnectionResponse is the updated source node returned by
1721+
// [Client.RerouteNodeConnection] (its fields stay flat via the embedded type)
1722+
// plus the latest simplified workflow.
1723+
type RerouteNodeConnectionResponse struct {
1724+
WorkflowMutationNodeWithRevision
1725+
Workflow SimplifiedWorkflow `json:"workflow"`
1726+
}
1727+
1728+
// UnmarshalJSON decodes the node and revision via the embedded type and then
1729+
// the latest workflow.
1730+
func (n *RerouteNodeConnectionResponse) UnmarshalJSON(data []byte) error {
1731+
if err := n.WorkflowMutationNodeWithRevision.UnmarshalJSON(data); err != nil {
1732+
return err
1733+
}
1734+
var extra struct {
1735+
Workflow SimplifiedWorkflow `json:"workflow"`
1736+
}
1737+
if err := json.Unmarshal(data, &extra); err != nil {
1738+
return err
1739+
}
1740+
n.Workflow = extra.Workflow
1741+
return nil
1742+
}
1743+
1744+
// MarshalJSON encodes the embedded node and revision and adds the workflow.
1745+
func (n RerouteNodeConnectionResponse) MarshalJSON() ([]byte, error) {
1746+
return mergeMarshal(n.WorkflowMutationNodeWithRevision, map[string]any{"workflow": n.Workflow})
1747+
}
1748+
1749+
// RerouteNodeConnection moves the single outgoing connection of the source node
1750+
// identified by workflowID/nodeID to req.NewTargetNodeID, returning the updated
1751+
// source node and the latest workflow. The source node must have exactly one
1752+
// outgoing connection; branch and experiment branch nodes cannot be rerouted.
1753+
func (c *Client) RerouteNodeConnection(workflowID, nodeID string, req RerouteNodeConnectionRequest) (*RerouteNodeConnectionResponse, error) {
1754+
body := map[string]any{
1755+
"expectedRevisionId": req.ExpectedRevisionID,
1756+
"newTargetNodeId": req.NewTargetNodeID,
1757+
}
1758+
1759+
b, err := json.Marshal(body)
1760+
if err != nil {
1761+
return nil, fmt.Errorf("failed to encode request: %w", err)
1762+
}
1763+
1764+
httpReq, err := c.newRequest(http.MethodPost, "/workflows/"+workflowID+"/nodes/"+nodeID+"/reroute", bytes.NewReader(b))
1765+
if err != nil {
1766+
return nil, err
1767+
}
1768+
1769+
resp, err := c.do(httpReq)
1770+
if err != nil {
1771+
return nil, err
1772+
}
1773+
defer resp.Body.Close()
1774+
1775+
if resp.StatusCode != http.StatusOK {
1776+
return nil, errorFromResponse(resp)
1777+
}
1778+
1779+
var result RerouteNodeConnectionResponse
1780+
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
1781+
return nil, fmt.Errorf("failed to decode response: %w", err)
1782+
}
1783+
1784+
return &result, nil
1785+
}

0 commit comments

Comments
 (0)