Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions src/Resend/Automation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ public class Automation
public List<AutomationStep> Steps { get; set; } = default!;

/// <summary>
/// Edges connecting steps.
/// Connections between steps.
/// </summary>
[JsonPropertyName( "edges" )]
public List<AutomationEdge> Edges { get; set; } = default!;
[JsonPropertyName( "connections" )]
public List<AutomationEdge> Connections { get; set; } = default!;
Comment thread
zenorocha marked this conversation as resolved.
}
6 changes: 3 additions & 3 deletions src/Resend/AutomationCreateData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ public class AutomationCreateData
public List<AutomationStepData> Steps { get; set; } = default!;

/// <summary>
/// Edges between steps (may be empty for single-step automations).
/// Connections between steps (may be empty for single-step automations).
/// </summary>
[JsonPropertyName( "edges" )]
public List<AutomationEdge> Edges { get; set; } = default!;
[JsonPropertyName( "connections" )]
public List<AutomationEdge> Connections { get; set; } = default!;
}
4 changes: 2 additions & 2 deletions src/Resend/AutomationEdge.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ public class AutomationEdge
public string To { get; set; } = default!;

/// <summary>
/// Edge kind: <c>default</c>, <c>condition_met</c>, <c>condition_not_met</c>, <c>timeout</c>, <c>event_received</c>.
/// Connection type: <c>default</c>, <c>condition_met</c>, <c>condition_not_met</c>, <c>timeout</c>, <c>event_received</c>.
/// </summary>
[JsonPropertyName( "edge_type" )]
[JsonPropertyName( "type" )]
[JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
public string? EdgeType { get; set; }
}
2 changes: 1 addition & 1 deletion src/Resend/AutomationRun.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public class AutomationRun
/// </summary>
[JsonPropertyName( "started_at" )]
[JsonConverter( typeof( JsonUtcDateTimeConverter ) )]
public DateTime MomentStarted { get; set; }
public DateTime? MomentStarted { get; set; }

/// <summary>
/// When the run finished, if applicable.
Expand Down
8 changes: 7 additions & 1 deletion src/Resend/AutomationRunStep.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ namespace Resend;
/// </summary>
public class AutomationRunStep
{
/// <summary>
/// Unique key identifying this step within the automation graph.
/// </summary>
[JsonPropertyName( "key" )]
public string? Key { get; set; }

/// <summary>
/// Step type.
/// </summary>
Expand All @@ -25,7 +31,7 @@ public class AutomationRunStep
/// </summary>
[JsonPropertyName( "started_at" )]
[JsonConverter( typeof( JsonUtcDateTimeConverter ) )]
public DateTime MomentStarted { get; set; }
public DateTime? MomentStarted { get; set; }

/// <summary>
/// When the step finished, if applicable.
Expand Down
2 changes: 1 addition & 1 deletion src/Resend/AutomationRunSummary.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public class AutomationRunSummary
/// </summary>
[JsonPropertyName( "started_at" )]
[JsonConverter( typeof( JsonUtcDateTimeConverter ) )]
public DateTime MomentStarted { get; set; }
public DateTime? MomentStarted { get; set; }

/// <summary>
/// When the run finished, if applicable.
Expand Down
8 changes: 7 additions & 1 deletion src/Resend/AutomationStep.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,16 @@
namespace Resend;

/// <summary>
/// A step returned when retrieving an automation (responses omit per-step <c>ref</c>).
/// A step returned when retrieving an automation.
/// </summary>
public class AutomationStep
{
/// <summary>
/// Unique key identifying this step within the automation graph.
/// </summary>
[JsonPropertyName( "key" )]
public string? Key { get; set; }

/// <summary>
/// Step type.
/// </summary>
Expand Down
6 changes: 3 additions & 3 deletions src/Resend/AutomationUpdateData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

/// <summary>
/// Request body to update an automation. Provide at least one field; when updating the graph,
/// send <see cref="Steps"/> and <see cref="Edges"/> together.

Check warning on line 7 in src/Resend/AutomationUpdateData.cs

View workflow job for this annotation

GitHub Actions / build

XML comment has cref attribute 'Edges' that could not be resolved

Check warning on line 7 in src/Resend/AutomationUpdateData.cs

View workflow job for this annotation

GitHub Actions / build

XML comment has cref attribute 'Edges' that could not be resolved
/// </summary>
public class AutomationUpdateData
{
Expand All @@ -30,9 +30,9 @@
public List<AutomationStepData>? Steps { get; set; }

/// <summary>
/// Replacement edge list when updating the graph.
/// Replacement connection list when updating the graph.
/// </summary>
[JsonPropertyName( "edges" )]
[JsonPropertyName( "connections" )]
[JsonIgnore( Condition = JsonIgnoreCondition.WhenWritingNull )]
public List<AutomationEdge>? Edges { get; set; }
public List<AutomationEdge>? Connections { get; set; }
}
27 changes: 27 additions & 0 deletions src/Resend/EventDeleteResult.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using System.Text.Json.Serialization;

namespace Resend;

/// <summary>
/// Response returned when deleting an event definition.
/// </summary>
public class EventDeleteResult
{
/// <summary>
/// Object type discriminator.
/// </summary>
[JsonPropertyName( "object" )]
public string Object { get; set; } = default!;

/// <summary>
/// Event identifier.
/// </summary>
[JsonPropertyName( "id" )]
public Guid Id { get; set; }

/// <summary>
/// Whether the event was deleted.
/// </summary>
[JsonPropertyName( "deleted" )]
public bool Deleted { get; set; }
}
2 changes: 1 addition & 1 deletion src/Resend/EventResource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,5 +45,5 @@ public class EventResource
/// </summary>
[JsonPropertyName( "updated_at" )]
[JsonConverter( typeof( JsonUtcDateTimeConverter ) )]
public DateTime MomentUpdated { get; set; }
public DateTime? MomentUpdated { get; set; }
}
16 changes: 8 additions & 8 deletions src/Resend/IResend.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1106,37 +1106,37 @@ public interface IResend
/// <param name="eventId">Event identifier.</param>
/// <param name="data">Fields to update.</param>
/// <param name="cancellationToken">Cancellation token.</param>
/// <returns>Response.</returns>
/// <returns>ID of the updated event.</returns>
/// <see href="https://resend.com/docs/api-reference/events/update-event"/>
Task<ResendResponse> EventUpdateAsync( Guid eventId, EventUpdateData data, CancellationToken cancellationToken = default );
Task<ResendResponse<Guid>> EventUpdateAsync( Guid eventId, EventUpdateData data, CancellationToken cancellationToken = default );

/// <summary>
/// Updates an event definition by identifier or name.
/// </summary>
/// <param name="eventIdOrName">Event id (UUID) or name.</param>
/// <param name="data">Fields to update.</param>
/// <param name="cancellationToken">Cancellation token.</param>
/// <returns>Response.</returns>
/// <returns>ID of the updated event.</returns>
/// <see href="https://resend.com/docs/api-reference/events/update-event"/>
Task<ResendResponse> EventUpdateAsync( string eventIdOrName, EventUpdateData data, CancellationToken cancellationToken = default );
Task<ResendResponse<Guid>> EventUpdateAsync( string eventIdOrName, EventUpdateData data, CancellationToken cancellationToken = default );

/// <summary>
/// Deletes an event definition.
/// </summary>
/// <param name="eventId">Event identifier.</param>
/// <param name="cancellationToken">Cancellation token.</param>
/// <returns>Response.</returns>
/// <returns>Delete result including the event id and confirmation flag.</returns>
/// <see href="https://resend.com/docs/api-reference/events/delete-event"/>
Task<ResendResponse> EventDeleteAsync( Guid eventId, CancellationToken cancellationToken = default );
Task<ResendResponse<EventDeleteResult>> EventDeleteAsync( Guid eventId, CancellationToken cancellationToken = default );

/// <summary>
/// Deletes an event definition by identifier or name.
/// </summary>
/// <param name="eventIdOrName">Event id (UUID) or name.</param>
/// <param name="cancellationToken">Cancellation token.</param>
/// <returns>Response.</returns>
/// <returns>Delete result including the event id and confirmation flag.</returns>
/// <see href="https://resend.com/docs/api-reference/events/delete-event"/>
Task<ResendResponse> EventDeleteAsync( string eventIdOrName, CancellationToken cancellationToken = default );
Task<ResendResponse<EventDeleteResult>> EventDeleteAsync( string eventIdOrName, CancellationToken cancellationToken = default );

/// <summary>
/// Sends a named event (for example to trigger automations).
Expand Down
16 changes: 8 additions & 8 deletions src/Resend/ResendClient.Events.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,40 +63,40 @@ public partial class ResendClient


/// <inheritdoc />
public Task<ResendResponse> EventUpdateAsync( Guid eventId, EventUpdateData data, CancellationToken cancellationToken = default )
public Task<ResendResponse<Guid>> 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<ObjectId, Guid>( req, ( x ) => x.Id, cancellationToken );
}


/// <inheritdoc />
public Task<ResendResponse> EventUpdateAsync( string eventIdOrName, EventUpdateData data, CancellationToken cancellationToken = default )
public Task<ResendResponse<Guid>> 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<ObjectId, Guid>( req, ( x ) => x.Id, cancellationToken );
}


/// <inheritdoc />
public Task<ResendResponse> EventDeleteAsync( Guid eventId, CancellationToken cancellationToken = default )
public Task<ResendResponse<EventDeleteResult>> EventDeleteAsync( Guid eventId, CancellationToken cancellationToken = default )
{
var req = new HttpRequestMessage( HttpMethod.Delete, $"/events/{eventId}" );

return Execute( req, cancellationToken );
return Execute<EventDeleteResult, EventDeleteResult>( req, ( x ) => x, cancellationToken );
}


/// <inheritdoc />
public Task<ResendResponse> EventDeleteAsync( string eventIdOrName, CancellationToken cancellationToken = default )
public Task<ResendResponse<EventDeleteResult>> EventDeleteAsync( string eventIdOrName, CancellationToken cancellationToken = default )
{
var req = new HttpRequestMessage( HttpMethod.Delete, $"/events/{Uri.EscapeDataString( eventIdOrName )}" );

return Execute( req, cancellationToken );
return Execute<EventDeleteResult, EventDeleteResult>( req, ( x ) => x, cancellationToken );
}


Expand Down
2 changes: 1 addition & 1 deletion tests/Resend.Tests/ResendClientTests.Automations.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public async Task AutomationCreate()
Config = JsonDocument.Parse( "{\"event_name\":\"user.created\"}" ).RootElement,
},
],
Edges = [],
Connections = [],
} );

Assert.NotNull( resp );
Expand Down
9 changes: 8 additions & 1 deletion tests/Resend.Tests/ResendClientTests.Events.cs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ public async Task EventUpdate_ByName()

Assert.NotNull( resp );
Assert.True( resp.Success );
Assert.NotEqual( Guid.Empty, resp.Content );
}


Expand All @@ -104,6 +105,7 @@ public async Task EventUpdate_ByGuid()

Assert.NotNull( resp );
Assert.True( resp.Success );
Assert.NotEqual( Guid.Empty, resp.Content );
}


Expand All @@ -115,17 +117,22 @@ public async Task EventDelete_ByName()

Assert.NotNull( resp );
Assert.True( resp.Success );
Assert.True( resp.Content.Deleted );
}


/// <summary/>
[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 );
}


Expand Down
6 changes: 5 additions & 1 deletion tools/Resend.ApiServer/Controllers/AutomationController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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 <hello@example.com>\"}" ).RootElement,
},
],
Edges =
Connections =
[
new AutomationEdge()
{
Expand Down Expand Up @@ -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 ),
Expand All @@ -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 ),
Expand Down
17 changes: 15 additions & 2 deletions tools/Resend.ApiServer/Controllers/EventController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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" ),
} );
}


Expand All @@ -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,
} );
}


Expand Down
Loading