Try translating this QueryContext

This commit is contained in:
Jordan Dominion
2025-08-18 19:08:20 -04:00
parent b90e58b419
commit 26ab854270
2 changed files with 44 additions and 2 deletions
@@ -12,6 +12,48 @@ namespace Tgstation.Server.Host.Extensions
/// </summary>
static class QueryContextExtensions
{
/// <summary>
/// Convert a <see cref="QueryContext{TEntity}"/> to an equivalent one that operates on a given <typeparamref name="TChild"/> of the original <typeparamref name="TParent"/>.
/// </summary>
/// <typeparam name="TParent">The parent <see cref="Type"/>.</typeparam>
/// <typeparam name="TChild">The child <see cref="Type"/>.</typeparam>
/// <param name="queryContext">The <see cref="QueryContext{TEntity}"/> to transform.</param>
/// <returns>A new <see cref="QueryContext{TEntity}"/> for <typeparamref name="TChild"/> that is functionally identical to the original <paramref name="queryContext"/>.</returns>
public static QueryContext<TChild> UpcastFrom<TParent, TChild>(this QueryContext<TParent> queryContext)
where TChild : TParent
{
ArgumentNullException.ThrowIfNull(queryContext);
var parameter = Expression.Parameter(typeof(TChild), "child");
Expression<Func<TChild, TChild>>? selector = null;
if (queryContext.Selector != null)
{
Expression<Func<TParent, TChild>> upcast = parent => (TChild)parent!;
selector = Expression.Lambda<Func<TChild, TChild>>(
Expression.Invoke(
upcast,
Expression.Invoke(
queryContext.Selector,
parameter)),
parameter);
}
Expression<Func<TChild, bool>>? predicate = null;
if (queryContext.Predicate != null)
predicate = Expression.Lambda<Func<TChild, bool>>(
queryContext.Predicate,
parameter);
SortDefinition<TChild>? sortDefinition = null;
if (queryContext.Sorting?.Operations.Length > 0)
throw new NotImplementedException();
return new QueryContext<TChild>(
selector,
predicate,
sortDefinition);
}
/// <summary>
/// Translate a given <paramref name="queryContext"/> into one with the target wrapped in an <see cref="AuthorityResponse{TResult}"/>.
/// </summary>
@@ -127,7 +127,7 @@ namespace Tgstation.Server.Host.GraphQL.Types
/// <returns>The <see cref="IUserName"/> that created this <see cref="User"/>, if any.</returns>
public async ValueTask<IUserName?> CreatedBy(
[Service] IGraphQLAuthorityInvoker<IUserAuthority> userAuthority,
QueryContext<User>? queryContext,
QueryContext<IUserName>? queryContext,
CancellationToken cancellationToken)
{
ArgumentNullException.ThrowIfNull(userAuthority);
@@ -135,7 +135,7 @@ namespace Tgstation.Server.Host.GraphQL.Types
// This one is particular and cannot be data-loaded due to necessitating a different parameter
var user = await userAuthority.InvokeTransformable<Models.User, User, UserTransformer>(
authority => authority.GetId<User>(CreatedById, true, cancellationToken),
queryContext);
queryContext?.UpcastFrom<IUserName, User>());
if (user == null)
throw new InvalidOperationException($"Query for created by of user ID {CreatedById} returned null!");