Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update Node Entity Configuration #32

Merged
merged 10 commits into from
Jan 3, 2025
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using BuildingBlocks.Domain.ValueObjects.Ids;

namespace BuildingBlocks.Api.Converters;

public class FileIdConverter : IRegister
{
public void Register(TypeAdapterConfig config) =>
config.NewConfig<FileAssetId, FileAssetId>().ConstructUsing(src => FileAssetId.Of(src.Value));
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using BuildingBlocks.Domain.ValueObjects.Ids;

namespace BuildingBlocks.Api.Converters;

public class NodeIdConverter : IRegister
{
public void Register(TypeAdapterConfig config) =>
config.NewConfig<NodeId, NodeId>().ConstructUsing(src => NodeId.Of(src.Value));
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using BuildingBlocks.Domain.ValueObjects.Ids;

namespace BuildingBlocks.Api.Converters;

public class NoteIdConverter : IRegister
{
public void Register(TypeAdapterConfig config) =>
config.NewConfig<NoteId, NoteId>().ConstructUsing(src => NoteId.Of(src.Value));
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using BuildingBlocks.Domain.ValueObjects.Ids;

namespace BuildingBlocks.Api.Converters;

public class ReminderIdConverter : IRegister
{
public void Register(TypeAdapterConfig config) =>
config.NewConfig<ReminderId, ReminderId>().ConstructUsing(src => ReminderId.Of(src.Value));
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using BuildingBlocks.Domain.ValueObjects.Ids;

namespace BuildingBlocks.Api.Converters;

public class TimelineIdConverter : IRegister
{
public void Register(TypeAdapterConfig config) =>
config.NewConfig<TimelineId, TimelineId>().ConstructUsing(src => TimelineId.Of(src.Value));
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
global using Mapster;
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
using System.Text.Json.Serialization;
namespace BuildingBlocks.Domain.ValueObjects.Ids;

namespace BuildingBlocks.Domain.ValueObjects.Ids;

[JsonConverter(typeof(FileAssetIdJsonConverter))]
public record FileAssetId : StronglyTypedId
public class FileAssetId : StronglyTypedId
{
private FileAssetId(Guid value) : base(value) { }

public static FileAssetId Of(Guid value) => new(value);

private class FileAssetIdJsonConverter : StronglyTypedIdJsonConverter<FileAssetId>;
public override string ToString() => Value.ToString();
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
using System.Text.Json.Serialization;
namespace BuildingBlocks.Domain.ValueObjects.Ids;

namespace BuildingBlocks.Domain.ValueObjects.Ids;

[JsonConverter(typeof(NodeIdJsonConverter))]
public record NodeId : StronglyTypedId
public class NodeId : StronglyTypedId
{
private NodeId(Guid value) : base(value) { }

public static NodeId Of(Guid value) => new(value);

private class NodeIdJsonConverter : StronglyTypedIdJsonConverter<NodeId>;
public override string ToString() => Value.ToString();
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
using System.Text.Json.Serialization;
namespace BuildingBlocks.Domain.ValueObjects.Ids;

namespace BuildingBlocks.Domain.ValueObjects.Ids;

[JsonConverter(typeof(NoteIdJsonConverter))]
public record NoteId : StronglyTypedId
public class NoteId : StronglyTypedId
{
private NoteId(Guid value) : base(value) { }

public static NoteId Of(Guid value) => new(value);

private class NoteIdJsonConverter : StronglyTypedIdJsonConverter<NoteId>;
public override string ToString() => Value.ToString();
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
using System.Text.Json.Serialization;
namespace BuildingBlocks.Domain.ValueObjects.Ids;

namespace BuildingBlocks.Domain.ValueObjects.Ids;

[JsonConverter(typeof(ReminderIdJsonConverter))]
public record ReminderId : StronglyTypedId
public class ReminderId : StronglyTypedId
{
private ReminderId(Guid value) : base(value) { }

public static ReminderId Of(Guid value) => new(value);

private class ReminderIdJsonConverter : StronglyTypedIdJsonConverter<ReminderId>;
public override string ToString() => Value.ToString();
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
using System.Text.Json.Serialization;
namespace BuildingBlocks.Domain.ValueObjects.Ids;

namespace BuildingBlocks.Domain.ValueObjects.Ids;

[JsonConverter(typeof(TimelineIdJsonConverter))]
public record TimelineId : StronglyTypedId
public class TimelineId : StronglyTypedId
{
private TimelineId(Guid value) : base(value) { }

public static TimelineId Of(Guid value) => new(value);

private class TimelineIdJsonConverter : StronglyTypedIdJsonConverter<TimelineId>;
public override string ToString() => Value.ToString();
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
using System.Text.Json.Serialization;
using System.Text.Json;
namespace BuildingBlocks.Domain.ValueObjects;

namespace BuildingBlocks.Domain.ValueObjects;

public abstract record StronglyTypedId
public abstract class StronglyTypedId
{
protected StronglyTypedId(Guid value)
{
Expand All @@ -14,27 +11,6 @@ protected StronglyTypedId(Guid value)
}

public Guid Value { get; }

public override string ToString() => Value.ToString();
}

public class StronglyTypedIdJsonConverter<T> : JsonConverter<T> where T : StronglyTypedId
{
public override T Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
var value = reader.GetString();

if (Guid.TryParse(value, out var guid))
{
var constructor = typeof(T).GetConstructor(new[] { typeof(Guid) });

if (constructor != null)
return (T)constructor.Invoke(new object[] { guid });
}

throw new JsonException($"Invalid GUID format for {typeof(T).Name}: {value}");
}

public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options) =>
writer.WriteStringValue(value.Value.ToString());

public abstract override string ToString();
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using BuildingBlocks.Api.Converters;
using Files.Application.Extensions;
using Files.Infrastructure;
using Microsoft.Extensions.Configuration;
Expand All @@ -19,6 +20,8 @@ public static IServiceCollection AddFilesModule

private static IServiceCollection AddApiServices(this IServiceCollection services)
{
TypeAdapterConfig.GlobalSettings.Scan(typeof(FileIdConverter).Assembly);

return services;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ public static IServiceCollection AddApplicationServices(this IServiceCollection
config.AddOpenBehavior(typeof(LoggingBehavior<,>));
});

services.AddValidatorsFromAssembly(Assembly.GetExecutingAssembly());

return services;
}
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using BuildingBlocks.Api.Converters;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Nodes.Application.Extensions;
Expand All @@ -19,6 +20,8 @@ public static IServiceCollection AddNodesModule

private static IServiceCollection AddApiServices(this IServiceCollection services)
{
TypeAdapterConfig.GlobalSettings.Scan(typeof(NodeIdConverter).Assembly);

return services;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,37 @@ public CreateNodeCommandValidator()
RuleFor(x => x.Node.Title)
.NotEmpty().WithMessage("Title is required.")
.MaximumLength(100).WithMessage("Title must not exceed 100 characters.");

RuleFor(x => x.Node.Description)
.NotEmpty().WithMessage("Description is required.")
.MaximumLength(500).WithMessage("Description must not exceed 500 characters.");

// ToDo: Add remaining Node command validators
RuleFor(x => x.Node.Timestamp)
.LessThanOrEqualTo(DateTime.Now).WithMessage("Timestamp cannot be in the future.");

RuleFor(x => x.Node.Importance)
.InclusiveBetween(1, 10).WithMessage("Importance must be between 1 and 10.");

RuleFor(x => x.Node.Phase)
.NotEmpty().WithMessage("Phase is required.");

RuleFor(x => x.Node)
.NotNull().WithMessage("Node cannot be null.")
.DependentRules(() =>
{
RuleFor(x => x.Node.Categories)
.Must(categories => categories != null && categories.Count > 0)
.WithMessage("At least one category must be provided.");

RuleFor(x => x.Node.Tags)
.Must(tags => tags != null && tags.Count > 0)
.WithMessage("At least one tag must be provided.");
});

RuleForEach(x => x.Node.Categories)
.MaximumLength(50).WithMessage("Category must not exceed 50 characters.");

RuleForEach(x => x.Node.Tags)
.MaximumLength(50).WithMessage("Tag must not exceed 50 characters.");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ public static IServiceCollection AddApplicationServices(this IServiceCollection
config.AddOpenBehavior(typeof(LoggingBehavior<,>));
});

services.AddValidatorsFromAssembly(Assembly.GetExecutingAssembly());

return services;
}
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,28 @@
using Microsoft.EntityFrameworkCore.Metadata.Builders;

namespace Nodes.Infrastructure.Data.Configurations;

public class NodeConfiguration : IEntityTypeConfiguration<Node>
{
public void Configure(EntityTypeBuilder<Node> builder)
{
builder.HasKey(n => n.Id);
builder.Property(n => n.Id).HasConversion(
nodeId => nodeId.Value,
dbId => NodeId.Of(dbId));

// ToDo: Add remaining Node configuration commands
}
}
using Microsoft.EntityFrameworkCore.Metadata.Builders;

namespace Nodes.Infrastructure.Data.Configurations;

public class NodeConfiguration : IEntityTypeConfiguration<Node>
{
public void Configure(EntityTypeBuilder<Node> builder)
{
builder.HasKey(n => n.Id);
builder.Property(n => n.Id).HasConversion(
nodeId => nodeId.Value,
dbId => NodeId.Of(dbId));

builder.Property(n => n.Title)
.IsRequired()
.HasMaxLength(100);

builder.Property(n => n.Description)
.IsRequired()
.HasMaxLength(500);

builder.Property(n => n.Importance)
.IsRequired();

builder.Property(n => n.Phase)
.IsRequired();
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading