diff --git a/src/Resend/Automation.cs b/src/Resend/Automation.cs index b28df6f..55b482b 100644 --- a/src/Resend/Automation.cs +++ b/src/Resend/Automation.cs @@ -52,8 +52,8 @@ public class Automation public List Steps { get; set; } = default!; /// - /// Edges connecting steps. + /// Connections between steps. /// - [JsonPropertyName( "edges" )] - public List Edges { get; set; } = default!; + [JsonPropertyName( "connections" )] + public List Connections { get; set; } = default!; } diff --git a/src/Resend/AutomationCreateData.cs b/src/Resend/AutomationCreateData.cs index 97cb85e..4db51cf 100644 --- a/src/Resend/AutomationCreateData.cs +++ b/src/Resend/AutomationCreateData.cs @@ -27,8 +27,8 @@ public class AutomationCreateData public List Steps { get; set; } = default!; /// - /// Edges between steps (may be empty for single-step automations). + /// Connections between steps (may be empty for single-step automations). /// - [JsonPropertyName( "edges" )] - public List Edges { get; set; } = default!; + [JsonPropertyName( "connections" )] + public List Connections { get; set; } = default!; } diff --git a/src/Resend/AutomationEdge.cs b/src/Resend/AutomationEdge.cs index ac19d5d..46fce77 100644 --- a/src/Resend/AutomationEdge.cs +++ b/src/Resend/AutomationEdge.cs @@ -24,9 +24,9 @@ public class AutomationEdge public string To { get; set; } = default!; /// - /// Edge kind: default, condition_met, condition_not_met, timeout, event_received. + /// Connection type: default, condition_met, condition_not_met, timeout, event_received. /// - [JsonPropertyName( "edge_type" )] + [JsonPropertyName( "type" )] [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )] public string? EdgeType { get; set; } } diff --git a/src/Resend/AutomationRun.cs b/src/Resend/AutomationRun.cs index 0ce24b9..b5685ba 100644 --- a/src/Resend/AutomationRun.cs +++ b/src/Resend/AutomationRun.cs @@ -30,7 +30,7 @@ public class AutomationRun /// [JsonPropertyName( "started_at" )] [JsonConverter( typeof( JsonUtcDateTimeConverter ) )] - public DateTime MomentStarted { get; set; } + public DateTime? MomentStarted { get; set; } /// /// When the run finished, if applicable. diff --git a/src/Resend/AutomationRunStep.cs b/src/Resend/AutomationRunStep.cs index 0512cd3..b8282ad 100644 --- a/src/Resend/AutomationRunStep.cs +++ b/src/Resend/AutomationRunStep.cs @@ -8,6 +8,12 @@ namespace Resend; /// public class AutomationRunStep { + /// + /// Unique key identifying this step within the automation graph. + /// + [JsonPropertyName( "key" )] + public string? Key { get; set; } + /// /// Step type. /// @@ -25,7 +31,7 @@ public class AutomationRunStep /// [JsonPropertyName( "started_at" )] [JsonConverter( typeof( JsonUtcDateTimeConverter ) )] - public DateTime MomentStarted { get; set; } + public DateTime? MomentStarted { get; set; } /// /// When the step finished, if applicable. diff --git a/src/Resend/AutomationRunSummary.cs b/src/Resend/AutomationRunSummary.cs index 4175583..8cd09be 100644 --- a/src/Resend/AutomationRunSummary.cs +++ b/src/Resend/AutomationRunSummary.cs @@ -24,7 +24,7 @@ public class AutomationRunSummary /// [JsonPropertyName( "started_at" )] [JsonConverter( typeof( JsonUtcDateTimeConverter ) )] - public DateTime MomentStarted { get; set; } + public DateTime? MomentStarted { get; set; } /// /// When the run finished, if applicable. diff --git a/src/Resend/AutomationStep.cs b/src/Resend/AutomationStep.cs index 20c1495..76eccf2 100644 --- a/src/Resend/AutomationStep.cs +++ b/src/Resend/AutomationStep.cs @@ -4,10 +4,16 @@ namespace Resend; /// -/// A step returned when retrieving an automation (responses omit per-step ref). +/// A step returned when retrieving an automation. /// public class AutomationStep { + /// + /// Unique key identifying this step within the automation graph. + /// + [JsonPropertyName( "key" )] + public string? Key { get; set; } + /// /// Step type. /// diff --git a/src/Resend/AutomationUpdateData.cs b/src/Resend/AutomationUpdateData.cs index 059528f..be4174c 100644 --- a/src/Resend/AutomationUpdateData.cs +++ b/src/Resend/AutomationUpdateData.cs @@ -30,9 +30,9 @@ public class AutomationUpdateData public List? Steps { get; set; } /// - /// Replacement edge list when updating the graph. + /// Replacement connection list when updating the graph. /// - [JsonPropertyName( "edges" )] + [JsonPropertyName( "connections" )] [JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )] - public List? Edges { get; set; } + public List? Connections { get; set; } } diff --git a/src/Resend/EventDeleteResult.cs b/src/Resend/EventDeleteResult.cs new file mode 100644 index 0000000..9e036bf --- /dev/null +++ b/src/Resend/EventDeleteResult.cs @@ -0,0 +1,27 @@ +using System.Text.Json.Serialization; + +namespace Resend; + +/// +/// Response returned when deleting an event definition. +/// +public class EventDeleteResult +{ + /// + /// Object type discriminator. + /// + [JsonPropertyName( "object" )] + public string Object { get; set; } = default!; + + /// + /// Event identifier. + /// + [JsonPropertyName( "id" )] + public Guid Id { get; set; } + + /// + /// Whether the event was deleted. + /// + [JsonPropertyName( "deleted" )] + public bool Deleted { get; set; } +} diff --git a/src/Resend/EventResource.cs b/src/Resend/EventResource.cs index eb23c34..e57387e 100644 --- a/src/Resend/EventResource.cs +++ b/src/Resend/EventResource.cs @@ -45,5 +45,5 @@ public class EventResource /// [JsonPropertyName( "updated_at" )] [JsonConverter( typeof( JsonUtcDateTimeConverter ) )] - public DateTime MomentUpdated { get; set; } + public DateTime? MomentUpdated { get; set; } } diff --git a/src/Resend/IResend.cs b/src/Resend/IResend.cs index e892165..ca00b1e 100644 --- a/src/Resend/IResend.cs +++ b/src/Resend/IResend.cs @@ -1106,9 +1106,9 @@ public interface IResend /// Event identifier. /// Fields to update. /// Cancellation token. - /// Response. + /// ID of the updated event. /// - Task EventUpdateAsync( Guid eventId, EventUpdateData data, CancellationToken cancellationToken = default ); + Task> EventUpdateAsync( Guid eventId, EventUpdateData data, CancellationToken cancellationToken = default ); /// /// Updates an event definition by identifier or name. @@ -1116,27 +1116,27 @@ public interface IResend /// Event id (UUID) or name. /// Fields to update. /// Cancellation token. - /// Response. + /// ID of the updated event. /// - Task EventUpdateAsync( string eventIdOrName, EventUpdateData data, CancellationToken cancellationToken = default ); + Task> EventUpdateAsync( string eventIdOrName, EventUpdateData data, CancellationToken cancellationToken = default ); /// /// Deletes an event definition. /// /// Event identifier. /// Cancellation token. - /// Response. + /// Delete result including the event id and confirmation flag. /// - Task EventDeleteAsync( Guid eventId, CancellationToken cancellationToken = default ); + Task> EventDeleteAsync( Guid eventId, CancellationToken cancellationToken = default ); /// /// Deletes an event definition by identifier or name. /// /// Event id (UUID) or name. /// Cancellation token. - /// Response. + /// Delete result including the event id and confirmation flag. /// - Task EventDeleteAsync( string eventIdOrName, CancellationToken cancellationToken = default ); + Task> EventDeleteAsync( string eventIdOrName, CancellationToken cancellationToken = default ); /// /// Sends a named event (for example to trigger automations). diff --git a/src/Resend/ResendClient.Events.cs b/src/Resend/ResendClient.Events.cs index 888cef0..2e63fd8 100644 --- a/src/Resend/ResendClient.Events.cs +++ b/src/Resend/ResendClient.Events.cs @@ -63,40 +63,40 @@ public partial class ResendClient /// - public Task EventUpdateAsync( Guid eventId, EventUpdateData data, CancellationToken cancellationToken = default ) + public Task> EventUpdateAsync( Guid eventId, EventUpdateData data, CancellationToken cancellationToken = default ) { var req = new HttpRequestMessage( HttpMethod.Patch, $"/events/{eventId}" ); req.Content = JsonContent.Create( data ); - return Execute( req, cancellationToken ); + return Execute( req, ( x ) => x.Id, cancellationToken ); } /// - public Task EventUpdateAsync( string eventIdOrName, EventUpdateData data, CancellationToken cancellationToken = default ) + public Task> EventUpdateAsync( string eventIdOrName, EventUpdateData data, CancellationToken cancellationToken = default ) { var req = new HttpRequestMessage( HttpMethod.Patch, $"/events/{Uri.EscapeDataString( eventIdOrName )}" ); req.Content = JsonContent.Create( data ); - return Execute( req, cancellationToken ); + return Execute( req, ( x ) => x.Id, cancellationToken ); } /// - public Task EventDeleteAsync( Guid eventId, CancellationToken cancellationToken = default ) + public Task> EventDeleteAsync( Guid eventId, CancellationToken cancellationToken = default ) { var req = new HttpRequestMessage( HttpMethod.Delete, $"/events/{eventId}" ); - return Execute( req, cancellationToken ); + return Execute( req, ( x ) => x, cancellationToken ); } /// - public Task EventDeleteAsync( string eventIdOrName, CancellationToken cancellationToken = default ) + public Task> EventDeleteAsync( string eventIdOrName, CancellationToken cancellationToken = default ) { var req = new HttpRequestMessage( HttpMethod.Delete, $"/events/{Uri.EscapeDataString( eventIdOrName )}" ); - return Execute( req, cancellationToken ); + return Execute( req, ( x ) => x, cancellationToken ); } diff --git a/tests/Resend.Tests/ResendClientTests.Automations.cs b/tests/Resend.Tests/ResendClientTests.Automations.cs index 6c444f3..2d6ad4b 100644 --- a/tests/Resend.Tests/ResendClientTests.Automations.cs +++ b/tests/Resend.Tests/ResendClientTests.Automations.cs @@ -21,7 +21,7 @@ public async Task AutomationCreate() Config = JsonDocument.Parse( "{\"event_name\":\"user.created\"}" ).RootElement, }, ], - Edges = [], + Connections = [], } ); Assert.NotNull( resp ); diff --git a/tests/Resend.Tests/ResendClientTests.Events.cs b/tests/Resend.Tests/ResendClientTests.Events.cs index eef7a73..05f25c8 100644 --- a/tests/Resend.Tests/ResendClientTests.Events.cs +++ b/tests/Resend.Tests/ResendClientTests.Events.cs @@ -88,6 +88,7 @@ public async Task EventUpdate_ByName() Assert.NotNull( resp ); Assert.True( resp.Success ); + Assert.NotEqual( Guid.Empty, resp.Content ); } @@ -104,6 +105,7 @@ public async Task EventUpdate_ByGuid() Assert.NotNull( resp ); Assert.True( resp.Success ); + Assert.NotEqual( Guid.Empty, resp.Content ); } @@ -115,6 +117,7 @@ public async Task EventDelete_ByName() Assert.NotNull( resp ); Assert.True( resp.Success ); + Assert.True( resp.Content.Deleted ); } @@ -122,10 +125,14 @@ public async Task EventDelete_ByName() [Fact] public async Task EventDelete_ByGuid() { - var resp = await _resend.EventDeleteAsync( Guid.NewGuid() ); + var id = Guid.NewGuid(); + + var resp = await _resend.EventDeleteAsync( id ); Assert.NotNull( resp ); Assert.True( resp.Success ); + Assert.Equal( id, resp.Content.Id ); + Assert.True( resp.Content.Deleted ); } diff --git a/tools/Resend.ApiServer/Controllers/AutomationController.cs b/tools/Resend.ApiServer/Controllers/AutomationController.cs index 2446e61..506775d 100644 --- a/tools/Resend.ApiServer/Controllers/AutomationController.cs +++ b/tools/Resend.ApiServer/Controllers/AutomationController.cs @@ -71,16 +71,18 @@ public Automation AutomationRetrieve( [FromRoute] Guid id ) [ new AutomationStep() { + Key = stepA.ToString(), Type = "trigger", Config = JsonDocument.Parse( "{\"event_name\":\"user.created\"}" ).RootElement, }, new AutomationStep() { + Key = stepB.ToString(), Type = "send_email", Config = JsonDocument.Parse( "{\"template_id\":\"tpl_xxxxxxxxx\",\"subject\":\"Welcome!\",\"from\":\"Acme \"}" ).RootElement, }, ], - Edges = + Connections = [ new AutomationEdge() { @@ -227,6 +229,7 @@ public AutomationRun AutomationRunRetrieve( [FromRoute] Guid automationId, [From [ new AutomationRunStep() { + Key = "trigger-step", Type = "trigger", Status = "completed", MomentStarted = DateTime.Parse( "2025-10-01 12:00:00.000000+00", null, System.Globalization.DateTimeStyles.RoundtripKind ), @@ -237,6 +240,7 @@ public AutomationRun AutomationRunRetrieve( [FromRoute] Guid automationId, [From }, new AutomationRunStep() { + Key = "send-email-step", Type = "send_email", Status = "completed", MomentStarted = DateTime.Parse( "2025-10-01 12:00:01.000000+00", null, System.Globalization.DateTimeStyles.RoundtripKind ), diff --git a/tools/Resend.ApiServer/Controllers/EventController.cs b/tools/Resend.ApiServer/Controllers/EventController.cs index 5e1d4f5..6474c90 100644 --- a/tools/Resend.ApiServer/Controllers/EventController.cs +++ b/tools/Resend.ApiServer/Controllers/EventController.cs @@ -105,7 +105,13 @@ public IActionResult EventUpdate( [FromRoute] string id, [FromBody] EventUpdateD { _logger.LogDebug( "EventUpdate" ); - return Ok(); + var isGuid = Guid.TryParse( id, out var eid ); + + return Ok( new ObjectId() + { + Object = "event", + Id = isGuid ? eid : Guid.Parse( "a1b2c3d4-e5f6-7890-abcd-ef1234567890" ), + } ); } @@ -116,7 +122,14 @@ public IActionResult EventDelete( [FromRoute] string id ) { _logger.LogDebug( "EventDelete" ); - return Ok(); + var isGuid = Guid.TryParse( id, out var eid ); + + return Ok( new EventDeleteResult() + { + Object = "event", + Id = isGuid ? eid : Guid.Parse( "a1b2c3d4-e5f6-7890-abcd-ef1234567890" ), + Deleted = true, + } ); }