Skip to content

Commit a7f2a9e

Browse files
committed
Cleanup, first pass implementation of User, Project and Publisher collection event stream handlers
1 parent 0378c5a commit a7f2a9e

19 files changed

Lines changed: 532 additions & 19 deletions

src/IReadOnlyEntity.cs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,8 @@ namespace WindowsAppCommunity.Sdk;
55
/// <summary>
66
/// Represents a read-only entity with common properties and events.
77
/// </summary>
8-
public interface IReadOnlyEntity : IReadOnlyConnectionsCollection, IReadOnlyLinksCollection, IReadOnlyImagesCollection
8+
public interface IReadOnlyEntity : IReadOnlyConnectionsCollection, IReadOnlyLinksCollection, IReadOnlyImagesCollection, IHasId
99
{
10-
/// <summary>
11-
/// An Id corresponding to this object instance. This Id should be unique for the object, but identical across runs and environments.
12-
/// </summary>
13-
string Id { get; }
14-
1510
/// <summary>
1611
/// The name of the entity.
1712
/// </summary>

src/IReadOnlyProject.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
namespace WindowsAppCommunity.Sdk;
1+
using OwlCore.ComponentModel;
2+
3+
namespace WindowsAppCommunity.Sdk;
24

35
/// <summary>
46
/// Represents a project.
@@ -10,7 +12,7 @@ public interface IReadOnlyProject : IReadOnlyProject<IReadOnlyProjectCollection>
1012
/// <summary>
1113
/// Represents a project.
1214
/// </summary>
13-
public interface IReadOnlyProject<out TDependencyCollection> : IReadOnlyEntity, IReadOnlyImagesCollection, IReadOnlyUserRoleCollection, IReadOnlyAccentColor, IReadOnlyFeaturesCollection
15+
public interface IReadOnlyProject<out TDependencyCollection> : IReadOnlyEntity, IReadOnlyImagesCollection, IReadOnlyUserRoleCollection, IReadOnlyAccentColor, IReadOnlyFeaturesCollection, IHasId
1416
where TDependencyCollection : IReadOnlyProjectCollection<IReadOnlyProject>
1517
{
1618
/// <summary>

src/IReadOnlyProjectCollection.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System.Collections.Generic;
2+
using OwlCore.ComponentModel;
23

34
namespace WindowsAppCommunity.Sdk;
45

@@ -12,7 +13,7 @@ public interface IReadOnlyProjectCollection : IReadOnlyProjectCollection<IReadOn
1213
/// <summary>
1314
/// Represents a collection of projects.
1415
/// </summary>
15-
public interface IReadOnlyProjectCollection<TProject>
16+
public interface IReadOnlyProjectCollection<TProject> : IHasId
1617
where TProject : IReadOnlyProject
1718
{
1819
/// <summary>

src/IReadOnlyPublisher.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
namespace WindowsAppCommunity.Sdk;
1+
using OwlCore.ComponentModel;
2+
3+
namespace WindowsAppCommunity.Sdk;
24

35
/// <summary>
46
/// Represents a publisher, a collection of projects and collaborators who publish content to users.
@@ -10,7 +12,7 @@ public interface IReadOnlyPublisher : IReadOnlyPublisher<IReadOnlyPublisherColle
1012
/// <summary>
1113
/// Represents a publisher, a collection of projects and collaborators who publish content to users.
1214
/// </summary>
13-
public interface IReadOnlyPublisher<TPublisherCollection> : IReadOnlyEntity, IReadOnlyAccentColor, IReadOnlyUserRoleCollection, IReadOnlyProjectCollection
15+
public interface IReadOnlyPublisher<TPublisherCollection> : IReadOnlyEntity, IReadOnlyAccentColor, IReadOnlyUserRoleCollection, IReadOnlyProjectCollection, IHasId
1416
where TPublisherCollection : IReadOnlyPublisherCollection<IReadOnlyPublisher>
1517
{
1618
/// <summary>

src/IReadOnlyPublisherCollection.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System.Collections.Generic;
2+
using OwlCore.ComponentModel;
23

34
namespace WindowsAppCommunity.Sdk;
45

@@ -12,7 +13,7 @@ public interface IReadOnlyPublisherCollection : IReadOnlyPublisherCollection<IRe
1213
/// <summary>
1314
/// Represents a collection of publishers that can be read but not modified.
1415
/// </summary>
15-
public interface IReadOnlyPublisherCollection<TPublisher>
16+
public interface IReadOnlyPublisherCollection<TPublisher> : IHasId
1617
where TPublisher : IReadOnlyPublisher
1718
{
1819
/// <summary>

src/IReadOnlyUser.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1-
namespace WindowsAppCommunity.Sdk;
1+
using OwlCore.ComponentModel;
2+
3+
namespace WindowsAppCommunity.Sdk;
24

35
/// <summary>
46
/// Represents a user.
57
/// </summary>
6-
public interface IReadOnlyUser : IReadOnlyEntity, IReadOnlyPublisherRoleCollection, IReadOnlyProjectRoleCollection
8+
public interface IReadOnlyUser : IReadOnlyEntity, IReadOnlyPublisherRoleCollection, IReadOnlyProjectRoleCollection, IHasId
79
{
810
}

src/IReadOnlyUserCollection.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System.Collections.Generic;
2+
using OwlCore.ComponentModel;
23

34
namespace WindowsAppCommunity.Sdk;
45

@@ -13,7 +14,7 @@ public interface IReadOnlyUserCollection : IReadOnlyUserCollection<IReadOnlyUser
1314
/// Represents a collection of users with a corresponding role that can be modified.
1415
/// </summary>
1516
/// <typeparam name="TUser">The type of user in this collection.</typeparam>
16-
public interface IReadOnlyUserCollection<out TUser>
17+
public interface IReadOnlyUserCollection<out TUser> : IHasId
1718
where TUser : IReadOnlyUser
1819
{
1920
/// <summary>

src/Models/IUserRoleCollection.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
using System.Collections.Generic;
21
using Ipfs;
32

43
namespace WindowsAppCommunity.Sdk.Models;

src/Models/Role.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
using Newtonsoft.Json;
21
using OwlCore.Storage;
32

43
namespace WindowsAppCommunity.Sdk.Models;
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
using System.Collections.Generic;
2+
using System.Linq;
3+
using Ipfs;
4+
using OwlCore.Nomad;
5+
using OwlCore.Nomad.Kubo;
6+
using OwlCore.Nomad.Kubo.Events;
7+
8+
namespace WindowsAppCommunity.Sdk.Nomad;
9+
10+
/// <summary>
11+
/// A modifiable handler for roaming project collection data.
12+
/// </summary>
13+
public class ModifiableProjectCollection : NomadKuboEventStreamHandler<ValueUpdateEvent>, IModifiableProjectCollection<IReadOnlyProject>
14+
{
15+
/// <inheritdoc/>
16+
public required string Id { get; init; }
17+
18+
/// <inheritdoc/>
19+
public required ReadOnlyProjectCollection Inner { get; init; }
20+
21+
/// <inheritdoc/>
22+
public event EventHandler<IReadOnlyProject[]>? ProjectsAdded;
23+
24+
/// <inheritdoc/>
25+
public event EventHandler<IReadOnlyProject[]>? ProjectsRemoved;
26+
27+
/// <inheritdoc/>
28+
public IAsyncEnumerable<IReadOnlyProject> GetProjectsAsync(CancellationToken cancellationToken) => Inner.GetProjectsAsync(cancellationToken);
29+
30+
/// <inheritdoc/>
31+
public async Task AddProjectAsync(IReadOnlyProject project, CancellationToken cancellationToken)
32+
{
33+
var valueCid = await Client.Dag.PutAsync(project.Id, pin: KuboOptions.ShouldPin, cancel: cancellationToken);
34+
35+
var updateEvent = new ValueUpdateEvent(Key: null, Value: (DagCid)valueCid, false);
36+
37+
var appendedEntry = await AppendNewEntryAsync(targetId: Id, eventId: nameof(AddProjectAsync), updateEvent, DateTime.UtcNow, cancellationToken);
38+
await ApplyAddProjectEntryAsync(appendedEntry, updateEvent, project, cancellationToken);
39+
40+
EventStreamPosition = appendedEntry;
41+
}
42+
43+
/// <inheritdoc/>
44+
public async Task RemoveProjectAsync(IReadOnlyProject project, CancellationToken cancellationToken)
45+
{
46+
var valueCid = await Client.Dag.PutAsync(project.Id, pin: KuboOptions.ShouldPin, cancel: cancellationToken);
47+
48+
var updateEvent = new ValueUpdateEvent(Key: null, Value: (DagCid)valueCid, false);
49+
50+
var appendedEntry = await AppendNewEntryAsync(targetId: Id, eventId: nameof(RemoveProjectAsync), updateEvent, DateTime.UtcNow, cancellationToken);
51+
await ApplyRemoveProjectEntryAsync(appendedEntry, updateEvent, project, cancellationToken);
52+
53+
EventStreamPosition = appendedEntry;
54+
}
55+
56+
/// <inheritdoc/>
57+
public override async Task ApplyEntryUpdateAsync(EventStreamEntry<DagCid> streamEntry, ValueUpdateEvent updateEvent, CancellationToken cancellationToken)
58+
{
59+
switch (streamEntry.EventId)
60+
{
61+
case nameof(AddProjectAsync):
62+
// TODO: Needs project repository
63+
ReadOnlyProject addedProject = null!;
64+
await ApplyAddProjectEntryAsync(streamEntry, updateEvent, addedProject, cancellationToken);
65+
break;
66+
case nameof(RemoveProjectAsync):
67+
// TODO: Needs project repository
68+
ReadOnlyProject removedProject = null!;
69+
await ApplyRemoveProjectEntryAsync(streamEntry, updateEvent, removedProject, cancellationToken);
70+
break;
71+
default:
72+
throw new InvalidOperationException($"Unknown event id: {streamEntry.EventId}");
73+
}
74+
}
75+
76+
/// <inheritdoc/>
77+
public Task ApplyAddProjectEntryAsync(EventStreamEntry<DagCid> streamEntry, ValueUpdateEvent updateEvent, IReadOnlyProject project, CancellationToken cancellationToken)
78+
{
79+
Inner.Inner.Projects = [.. Inner.Inner.Projects, project.Id];
80+
ProjectsAdded?.Invoke(this, [project]);
81+
return Task.CompletedTask;
82+
}
83+
84+
/// <inheritdoc/>
85+
public Task ApplyRemoveProjectEntryAsync(EventStreamEntry<DagCid> streamEntry, ValueUpdateEvent updateEvent, IReadOnlyProject project, CancellationToken cancellationToken)
86+
{
87+
Inner.Inner.Projects = [.. Inner.Inner.Projects.Where(id => id != project.Id)];
88+
ProjectsRemoved?.Invoke(this, [project]);
89+
return Task.CompletedTask;
90+
91+
}
92+
93+
/// <inheritdoc/>
94+
public override Task ResetEventStreamPositionAsync(CancellationToken cancellationToken)
95+
{
96+
Inner.Inner.Projects = [];
97+
return Task.CompletedTask;
98+
}
99+
}

0 commit comments

Comments
 (0)