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

[3/4] Improve: Small Cleanup / Tech Debt Reduction Around NexusWebApi / V2 Types. #2095

Merged
merged 23 commits into from
Oct 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
78ace0f
WIP: Documentation for Update Detection
Sewer56 Sep 19, 2024
796c123
Added: Additional Edge Cases to Update Logic Docs
Sewer56 Sep 23, 2024
0cfb392
Added: Extra case of `Archived in the Middle`
Sewer56 Sep 23, 2024
6498415
Fixed: Indentation for `file_updates` field.
Sewer56 Sep 23, 2024
600ec0b
Finalized 'Updating Mods' doc with simplified Implementation requested.
Sewer56 Sep 24, 2024
2155750
Fixed: Minor Notes from older Research Doc
Sewer56 Sep 24, 2024
d151e86
Merge branch 'main' into detect-updates-docs-only
Sewer56 Sep 24, 2024
b54efac
Fixed: Added Missing 'Updating Mods' mkdocs sidebar item.
Sewer56 Sep 24, 2024
71a131b
[Working WIP] Added: Initial Implementation of Generic Page Caching S…
Sewer56 Sep 25, 2024
6fe3105
Merge remote-tracking branch 'origin/main' into updates-cache-system
Sewer56 Sep 26, 2024
7afd32d
Tech Debt Reduction: Add additional V2 GraphQL Types and Correct Size…
Sewer56 Sep 26, 2024
1173046
Added: Missing 'UInt32' types in attribute definitions
Sewer56 Sep 26, 2024
3eb2986
Improved: Accuracy of documentation for FileId struct.
Sewer56 Sep 26, 2024
2de875a
Added: Method for constructing UidForMod and UidForFile from GraphQL …
Sewer56 Sep 26, 2024
a0d80d4
Rename: ICanGetUid to ICanGetUidForMod
Sewer56 Sep 26, 2024
e8e09e3
Added: Tests for UidForModTests and UidForFileTests
Sewer56 Sep 27, 2024
e4349be
Removed: Unused Tests.cs file
Sewer56 Sep 27, 2024
2c96668
Merge branch 'updates-cache-system' into start-adding-v2-types
Sewer56 Sep 27, 2024
dbd6d20
Merge branch 'main' into start-adding-v2-types
Sewer56 Sep 30, 2024
731a620
Merge branch 'main' into start-adding-v2-types
Sewer56 Oct 1, 2024
edf3775
Merge remote-tracking branch 'origin/main' into start-adding-v2-types
Sewer56 Oct 2, 2024
a68e6dd
Merge branch 'main' into start-adding-v2-types
Sewer56 Oct 2, 2024
1498929
Merge branch 'main' into start-adding-v2-types
halgari Oct 3, 2024
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
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System.Text.Json.Serialization;
using NexusMods.Abstractions.NexusWebApi.Types;
using NexusMods.Abstractions.NexusWebApi.Types.V2;
using NexusMods.Paths;

namespace NexusMods.Abstractions.Collections.Json;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using JetBrains.Annotations;
using NexusMods.Abstractions.MnemonicDB.Attributes;
using NexusMods.Abstractions.NexusWebApi.Types;
using NexusMods.Abstractions.NexusWebApi.Types.V2;
using NexusMods.MnemonicDB.Abstractions.Attributes;
using NexusMods.MnemonicDB.Abstractions.Models;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using NexusMods.Abstractions.MnemonicDB.Attributes;
using NexusMods.Abstractions.NexusWebApi.Types;
using NexusMods.Abstractions.Resources.DB;
using NexusMods.Abstractions.NexusWebApi.Types.V2;
using NexusMods.Abstractions.Telemetry;
using NexusMods.MnemonicDB.Abstractions.Attributes;
using NexusMods.MnemonicDB.Abstractions.Models;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using System.Text.Json.Serialization;
using System.Text.Json.Serialization.Metadata;
using NexusMods.Abstractions.NexusWebApi.DTOs.Interfaces;
using GameId = NexusMods.Abstractions.NexusWebApi.Types.GameId;
using GameId = NexusMods.Abstractions.NexusWebApi.Types.V2.GameId;

// ReSharper disable MemberCanBePrivate.Global
// ReSharper disable InconsistentNaming
Expand All @@ -27,7 +27,7 @@ public class GameInfo : IJsonArraySerializable<GameInfo>
/// This field is for deserialization only.
/// </remarks>
[JsonPropertyName("id")]
public int _Id { get; set; }
public uint _Id { get; set; }

/// <summary>
/// Returns the ID as typed ValueObject <see cref="GameId"/>.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
using System.Text.Json.Serialization.Metadata;
using NexusMods.Abstractions.NexusWebApi.DTOs.Interfaces;
using NexusMods.Abstractions.NexusWebApi.Types;
using FileId = NexusMods.Abstractions.NexusWebApi.Types.FileId;
using NexusMods.Abstractions.NexusWebApi.Types.V2;
using FileId = NexusMods.Abstractions.NexusWebApi.Types.V2.FileId;

// 👇 Suppress uninitialised variables. Currently Nexus has mostly read-only API and we expect server to return the data.
#pragma warning disable CS8618
Expand Down Expand Up @@ -47,7 +48,7 @@ public class ModFile : IJsonSerializable<ModFile>
/// This ID is unique within the context of the game.
/// i.e. This ID might be used for another mod if you search for mods for another game.
/// </remarks>
public FileId FileId => FileId.From(_FileId);
public FileId FileId => FileId.From((uint)_FileId);

/// <summary>
/// Name (title) of the mod file as seen on the `Files` section of the mod page.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using System.Text.Json.Serialization;
using System.Text.Json.Serialization.Metadata;
using NexusMods.Abstractions.NexusWebApi.DTOs.Interfaces;
using ModId = NexusMods.Abstractions.NexusWebApi.Types.ModId;
using ModId = NexusMods.Abstractions.NexusWebApi.Types.V2.ModId;

// 👇 Suppress uninitialised variables. Currently Nexus has mostly read-only API and we expect server to return the data.
#pragma warning disable CS8618
Expand All @@ -25,7 +25,7 @@ public class ModUpdate : IJsonArraySerializable<ModUpdate>
/// <summary>
/// An individual mod ID that is unique for this game.
/// </summary>
public ModId ModId => ModId.From(_ModId);
public ModId ModId => ModId.From((uint)_ModId);

/// <summary>
/// The last time a file on the mod page was updated.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using NexusMods.Abstractions.NexusWebApi.DTOs;
using NexusMods.Abstractions.NexusWebApi.DTOs.OAuth;
using NexusMods.Abstractions.NexusWebApi.Types;
using FileId = NexusMods.Abstractions.NexusWebApi.Types.V2.FileId;
using ModId = NexusMods.Abstractions.NexusWebApi.Types.V2.ModId;

namespace NexusMods.Abstractions.NexusWebApi;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,8 @@
<ProjectReference Include="..\NexusMods.Abstractions.Serialization\NexusMods.Abstractions.Serialization.csproj" />
<PackageReference Include="NexusMods.MnemonicDB.SourceGenerator" PrivateAssets="all" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
</ItemGroup>

<ItemGroup>
<Folder Include="Types\V2\" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using NexusMods.Abstractions.NexusWebApi.Types;
using NexusMods.Abstractions.NexusWebApi.Types.V2;
using NexusMods.MnemonicDB.Abstractions.Attributes;
using NexusMods.MnemonicDB.Abstractions.Models;

Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ public class NXMModUrl : NXMUrl
/// <summary>
/// id of the mod page
/// </summary>
public ModId ModId { get; set; }
public V2.ModId ModId { get; set; }

/// <summary>
/// id of the file (within that game domain)
/// </summary>
public FileId FileId { get; set; }
public V2.FileId FileId { get; set; }

/// <summary>
/// game domain (name of the game within the Nexus Mods page)
Expand All @@ -36,8 +36,8 @@ public NXMModUrl(Uri uri)
Game = uri.Host;
try
{
ModId = ModId.From(ulong.Parse(uri.Segments[2].TrimEnd('/')));
FileId = FileId.From(ulong.Parse(uri.Segments[4].TrimEnd('/')));
ModId = V2.ModId.From(uint.Parse(uri.Segments[2].TrimEnd('/')));
FileId = V2.FileId.From(uint.Parse(uri.Segments[4].TrimEnd('/')));
}
catch (FormatException)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using NexusMods.MnemonicDB.Abstractions;
using NexusMods.MnemonicDB.Abstractions.Attributes;
using NexusMods.MnemonicDB.Abstractions.ElementComparers;
using TransparentValueObjects;
namespace NexusMods.Abstractions.NexusWebApi.Types.V2;

/// <summary>
/// Unique ID for a mod file associated with a game (<see cref="GameId"/>).
/// Querying mod pages returns items of this type.
/// </summary>
[ValueObject<uint>] // Matches backend. Do not change.
public readonly partial struct FileId : IAugmentWith<DefaultValueAugment>, IAugmentWith<JsonAugment>
{
/// <inheritdoc/>
public static FileId DefaultValue => From(default(uint));
}

/// <summary>
/// File ID attribute, for NexusMods API file IDs.
/// </summary>
public class FileIdAttribute(string ns, string name) :
ScalarAttribute<FileId, uint>(ValueTags.UInt32, ns, name)
{
/// <inheritdoc />
protected override uint ToLowLevel(FileId value) => value.Value;

/// <inheritdoc />
protected override FileId FromLowLevel(uint value, ValueTags tags, AttributeResolver resolver) => FileId.From(value);
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
using TransparentValueObjects;

namespace NexusMods.Abstractions.NexusWebApi.Types;
namespace NexusMods.Abstractions.NexusWebApi.Types.V2;

/// <summary>
/// Unique identifier for an individual game hosted on Nexus.
/// </summary>
[ValueObject<int>]
[ValueObject<uint>] // Matches backend. Do not change.
public readonly partial struct GameId : IAugmentWith<DefaultValueAugment>
{
/// <inheritdoc/>
public static GameId DefaultValue => From(default);
public static GameId DefaultValue => From(default(uint));
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,29 @@
using NexusMods.MnemonicDB.Abstractions.Attributes;
using NexusMods.MnemonicDB.Abstractions.ElementComparers;
using TransparentValueObjects;

namespace NexusMods.Abstractions.NexusWebApi.Types;
namespace NexusMods.Abstractions.NexusWebApi.Types.V2;

/// <summary>
/// An individual mod ID. Unique per game.
/// An individual mod ID. Unique per <see cref="GameId"/>.
/// i.e. Each game has its own set of IDs and starts with 0.
/// </summary>
[ValueObject<ulong>]
[ValueObject<uint>] // Matches backend. Do not change.
public readonly partial struct ModId : IAugmentWith<DefaultValueAugment>, IAugmentWith<JsonAugment>
{
/// <inheritdoc/>
public static ModId DefaultValue => From(default);
public static ModId DefaultValue => From(default(uint));
}


/// <summary>
/// Mod ID attribute, for NexusMods API mod IDs.
/// </summary>
public class ModIdAttribute(string ns, string name)
: ScalarAttribute<ModId, ulong>(ValueTags.UInt64, ns, name)
: ScalarAttribute<ModId, uint>(ValueTags.UInt32, ns, name)
{
/// <inheritdoc />
protected override ulong ToLowLevel(ModId value) => value.Value;
protected override uint ToLowLevel(ModId value) => value.Value;

/// <inheritdoc />
protected override ModId FromLowLevel(ulong value, ValueTags tags, AttributeResolver resolver) => ModId.From(value);
protected override ModId FromLowLevel(uint value, ValueTags tags, AttributeResolver resolver) => ModId.From(value);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace NexusMods.Abstractions.NexusWebApi.Types.V2.Uid;

/// <summary>
/// This represents a unique ID of an individual file as stored on Nexus Mods.
///
/// This is a composite key of <see cref="FileId"/> and <see cref="GameId"/>, where
/// the upper 4 bytes represent the <see cref="FileId"/> and the lower 4 bytes represent
/// the <see cref="GameId"/>.
///
/// This is consistent with how the Nexus Mods backend produces the UID and is not
/// expected to change.
/// </summary>
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct UidForFile
{
/// <summary>
/// Unique identifier for the file, within the specific <see cref="GameId"/>.
/// </summary>
public FileId FileId;

/// <summary>
/// Unique identifier for the game.
/// </summary>
public GameId GameId;

/// <summary>
/// Decodes a Nexus Mods API result which contains an 'uid' field into a <see cref="UidForFile"/>.
/// </summary>
/// <param name="uid">The 'uid' field of a GraphQL API query. This should be an 8 byte number represented as a string.</param>
/// <remarks>
/// This throws if <param name="uid"/> is not a valid number.
/// </remarks>
public static UidForFile FromV2Api(string uid) => FromUlong(ulong.Parse(uid));

/// <summary>
/// Reinterprets the current <see cref="UidForFile"/> as a single <see cref="ulong"/>.
/// </summary>
public ulong AsUlong => Unsafe.As<UidForFile, ulong>(ref this);

/// <summary>
/// Reinterprets a given <see cref="ulong"/> into a <see cref="UidForFile"/>.
/// </summary>
public static UidForFile FromUlong(ulong value) => Unsafe.As<ulong, UidForFile>(ref value);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace NexusMods.Abstractions.NexusWebApi.Types.V2.Uid;

/// <summary>
/// This represents a unique ID of an individual mod page as stored on Nexus Mods.
///
/// This is a composite key of <see cref="ModId"/> and <see cref="GameId"/>, where
/// the upper 4 bytes represent the <see cref="ModId"/> and the lower 4 bytes represent
/// the <see cref="GameId"/>. Values are stored in little endian byte order.
///
/// When transferred over the wire via the API, the resulting `ulong` is converted into
/// a string.
///
/// This is consistent with how the Nexus Mods backend produces the UID and is not
/// expected to change.
/// </summary>
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct UidForMod
{
/// <summary>
/// Unique identifier for the mod, within the specific <see cref="GameId"/>.
/// </summary>
public ModId ModId;

/// <summary>
/// Unique identifier for the game.
/// </summary>
public GameId GameId;

/// <summary>
/// Decodes a Nexus Mods API result which contains an 'uid' field into a <see cref="UidForFile"/>.
/// </summary>
/// <param name="uid">The 'uid' field of a GraphQL API query. This should be an 8 byte number represented as a string.</param>
/// <remarks>
/// This throws if <param name="uid"/> is not a valid number.
/// </remarks>
public static UidForMod FromV2Api(string uid) => FromUlong(ulong.Parse(uid));

/// <summary>
/// Reinterprets the current <see cref="UidForMod"/> as a single <see cref="ulong"/>.
/// </summary>
public ulong AsUlong => Unsafe.As<UidForMod, ulong>(ref this);

/// <summary>
/// Reinterprets a given <see cref="ulong"/> into a <see cref="UidForMod"/>.
/// </summary>
public static UidForMod FromUlong(ulong value) => Unsafe.As<ulong, UidForMod>(ref value);
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using DynamicData.Kernel;
using NexusMods.Abstractions.GameLocators;
using NexusMods.Abstractions.NexusWebApi.Types;
using NexusMods.Abstractions.NexusWebApi.Types.V2;
using NexusMods.Paths;

namespace NexusMods.Games.RedEngine.Cyberpunk2077.Emitters;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System.Text.RegularExpressions;
using NexusMods.Abstractions.GameLocators;
using NexusMods.Abstractions.NexusWebApi.Types;
using NexusMods.Abstractions.NexusWebApi.Types.V2;
using NexusMods.Paths;

namespace NexusMods.Games.RedEngine.Cyberpunk2077.Emitters;
Expand Down
4 changes: 2 additions & 2 deletions src/Games/NexusMods.Games.TestHarness/Verbs/StressTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
using NexusMods.ProxyConsole.Abstractions;
using NexusMods.ProxyConsole.Abstractions.VerbDefinitions;
using NexusMods.StandardGameLocators;
using ModId = NexusMods.Abstractions.NexusWebApi.Types.ModId;
using ModId = NexusMods.Abstractions.NexusWebApi.Types.V2.ModId;

namespace NexusMods.Games.TestHarness.Verbs;

Expand All @@ -38,7 +38,7 @@ internal static async Task<int> RunStressTest(
AdvancedManualInstallerUI.Headless = true;

var mods = await nexusApiClient.ModUpdatesAsync(game.Domain.Value, PastTime.Day, token);
var results = new List<(string FileName, ModId ModId, Abstractions.NexusWebApi.Types.FileId FileId, Hash Hash, bool Passed, Exception? exception)>();
var results = new List<(string FileName, ModId ModId, Abstractions.NexusWebApi.Types.V2.FileId FileId, Hash Hash, bool Passed, Exception? exception)>();

await using var gameFolder = temporaryFileManager.CreateFolder();
var (manualId, install) = await manualLocator.Add(game, new Version(1, 0), gameFolder);
Expand Down
Loading
Loading