< Summary

Line coverage
94%
Covered lines: 109
Uncovered lines: 6
Coverable lines: 115
Total lines: 319
Line coverage: 94.7%
Branch coverage
64%
Covered branches: 9
Total branches: 14
Branch coverage: 64.2%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
File 1: Initialize(...)100%22100%
File 1: GetWorks()100%11100%
File 1: GetWorks()58.33%121286.67%
File 2: GetWorks()100%11100%

File(s)

/home/runner/work/ProjectRead.ing/ProjectRead.ing/Api/obj/Debug/net10.0/generated/HotChocolate.Types.Analyzers/HotChocolate.Types.Analyzers.GraphQLServerGenerator/WorkQuery.UjLSLReKVUsGE0v90fV4zw.hc.g.cs

#LineLine coverage
 1// <auto-generated/>
 2
 3#nullable enable
 4#pragma warning disable
 5
 6using System;
 7using System.Runtime.CompilerServices;
 8using HotChocolate;
 9using HotChocolate.Types;
 10using HotChocolate.Execution.Configuration;
 11using Microsoft.Extensions.DependencyInjection;
 12using HotChocolate.Internal;
 13
 14namespace Api.Works.Queries
 15{
 16    public static partial class WorkQuery
 17    {
 18        internal static void Initialize(global::HotChocolate.Types.IObjectTypeDescriptor descriptor)
 119        {
 120            var extension = descriptor.Extend();
 121            var configuration = extension.Configuration;
 122            var thisType = typeof(global::Api.Works.Queries.WorkQuery);
 123            var bindingResolver = extension.Context.ParameterBindingResolver;
 124            var resolvers = new __Resolvers();
 25
 126            HotChocolate.Internal.ConfigurationHelper.ApplyConfiguration(
 127                extension.Context,
 128                descriptor,
 129                typeof(global::Api.Works.Queries.WorkQuery),
 130                new global::HotChocolate.Types.QueryTypeAttribute());
 131            configuration.ConfigurationsAreApplied = true;
 32
 133            var naming = descriptor.Extend().Context.Naming;
 34
 135            descriptor
 136                .Field(naming.GetMemberName("Works", global::HotChocolate.Types.MemberKind.ObjectField))
 137                .AddPagingArguments()
 138                .ExtendWith(static (field, context) =>
 139                {
 140                    var configuration = field.Configuration;
 141                    var typeInspector = field.Context.TypeInspector;
 142                    var bindingResolver = field.Context.ParameterBindingResolver;
 143                    var naming = field.Context.Naming;
 144
 145                    configuration.Type = typeInspector.GetTypeRef(typeof(global::HotChocolate.Types.NonNullType<global::
 146                    configuration.ResultType = typeof(global::HotChocolate.Types.Pagination.PageConnection<global::Api.W
 147                    configuration.DeclaringType = context.ThisType;
 148
 149                    configuration.SetSourceGeneratorFlags();
 150                    configuration.SetConnectionFlags();
 151                    var pagingOptions = global::HotChocolate.Types.Pagination.PagingHelper.GetPagingOptions(field.Contex
 152                    configuration.Features.Set(pagingOptions);
 153
 154                    configuration.Member = context.ThisType.GetMethod(
 155                        "GetWorks",
 156                        global::HotChocolate.Utilities.ReflectionUtils.StaticMemberFlags,
 157                        new global::System.Type[]
 158                        {
 159                            typeof(global::Api.Database.PGContext),
 160                            typeof(global::Api.Auth.Utils.ICurrentUserId),
 161                            typeof(global::Api.Works.Queries.WorkDataLoaders.IWorkByIdDataLoader),
 162                            typeof(global::GreenDonut.Data.QueryContext<global::Api.Works.Queries.Work>),
 163                            typeof(global::GreenDonut.Data.PagingArguments),
 164                            typeof(global::System.Threading.CancellationToken)
 165                        })!;
 166
 167                    var fieldDescriptor = global::HotChocolate.Types.Descriptors.ObjectFieldDescriptor.From(field.Contex
 168                    HotChocolate.Internal.ConfigurationHelper.ApplyConfiguration(
 169                        field.Context,
 170                        fieldDescriptor,
 171                        configuration.Member,
 172                        new global::HotChocolate.Types.UseConnectionAttribute(),
 173                        new global::Api.Auth.Handlers.PermissionCheckAuthorizeAttribute(global::Api.Auth.Models.UserPerm
 174                        new global::HotChocolate.Data.UseFilteringAttribute(null, 22),
 175                        new global::HotChocolate.Data.UseSortingAttribute(null, 23));
 176                    configuration.ConfigurationsAreApplied = true;
 177                    fieldDescriptor.CreateConfiguration();
 178
 179                    configuration.Resolvers = context.Resolvers.GetWorks();
 180                    configuration.ResultPostProcessor = global::HotChocolate.Execution.ListPostProcessor<global::Api.Wor
 181                },
 182                (Resolvers: resolvers, ThisType: thisType));
 83
 84            Configure(descriptor);
 185        }
 86
 87        static partial void Configure(global::HotChocolate.Types.IObjectTypeDescriptor descriptor);
 88
 89        private sealed class __Resolvers
 90        {
 91            public HotChocolate.Resolvers.FieldResolverDelegates GetWorks()
 192                => new global::HotChocolate.Resolvers.FieldResolverDelegates(resolver: GetWorks);
 93
 94            private async global::System.Threading.Tasks.ValueTask<global::System.Object?> GetWorks(global::HotChocolate
 195            {
 196                var args0 = context.Service<global::Api.Database.PGContext>();
 197                var args1 = context.Service<global::Api.Auth.Utils.ICurrentUserId>();
 198                var args2 = context.Service<global::Api.Works.Queries.WorkDataLoaders.IWorkByIdDataLoader>();
 199                var args3_selection = context.Selection;
 1100                var args3_filter = global::HotChocolate.Data.Filters.FilterContextResolverContextExtensions.GetFilterCon
 1101                var args3_sorting = global::HotChocolate.Data.Sorting.SortingContextResolverContextExtensions.GetSorting
 1102                var args3 = new global::GreenDonut.Data.QueryContext<global::Api.Works.Queries.Work>(
 1103                    global::HotChocolate.Execution.Processing.HotChocolateExecutionSelectionExtensions.AsSelector<global
 1104                    args3_filter?.AsPredicate<global::Api.Works.Queries.Work>(),
 1105                    args3_sorting?.AsSortDefinition<global::Api.Works.Queries.Work>());
 1106                var args4_options = global::HotChocolate.Types.Pagination.PagingHelper.GetPagingOptions(context.Schema, 
 1107                var args4_flags = global::HotChocolate.Types.Pagination.ConnectionFlagsHelper.GetConnectionFlags(context
 1108                var args4_first = context.ArgumentValue<int?>("first");
 1109                var args4_after = context.ArgumentValue<string?>("after");
 1110                int? args4_last = null;
 1111                string? args4_before = null;
 1112                bool args4_includeTotalCount = false;
 113
 1114                if(args4_options.AllowBackwardPagination ?? global::HotChocolate.Types.Pagination.PagingDefaults.AllowBa
 1115                {
 1116                    args4_last = context.ArgumentValue<int?>("last");
 1117                    args4_before = context.ArgumentValue<string?>("before");
 1118                }
 119
 1120                if(args4_first is null && args4_last is null)
 0121                {
 0122                    args4_first = args4_options.DefaultPageSize ?? global::HotChocolate.Types.Pagination.PagingDefaults.
 0123                }
 124
 1125                if(args4_options.IncludeTotalCount ?? global::HotChocolate.Types.Pagination.PagingDefaults.IncludeTotalC
 0126                {
 0127                    args4_includeTotalCount = args4_flags.HasFlag(global::HotChocolate.Types.Pagination.ConnectionFlags.
 0128                }
 129
 1130                var args4 = new global::GreenDonut.Data.PagingArguments(
 1131                    args4_first,
 1132                    args4_after,
 1133                    args4_last,
 1134                    args4_before,
 1135                    args4_includeTotalCount)
 1136                    {
 1137                        EnableRelativeCursors = args4_flags.HasFlag(global::HotChocolate.Types.Pagination.ConnectionFlag
 1138                        NullOrdering = args4_options.NullOrdering
 1139                    };
 1140                var args5 = context.RequestAborted;
 1141                var result = await global::Api.Works.Queries.WorkQuery.GetWorks(args0, args1, args2, args3, args4, args5
 1142                return result;
 1143            }
 144        }
 145    }
 146}
 147

/home/runner/work/ProjectRead.ing/ProjectRead.ing/Api/Works/Queries/Work.cs

#LineLine coverage
 1// SPDX-FileCopyrightText: 2026 Alper Çelik <[email protected]>
 2//
 3// SPDX-License-Identifier: AGPL-3.0-or-later
 4
 5using Api.Auth.Handlers;
 6using Api.Auth.Models;
 7using Api.Auth.Utils;
 8using Api.Database;
 9using GreenDonut.Data;
 10using HotChocolate.Types.Pagination;
 11using Microsoft.EntityFrameworkCore;
 12using Riok.Mapperly.Abstractions;
 13using static Api.Works.Queries.AuthorDataLoaders;
 14using static Api.Works.Queries.WorkDataLoaders;
 15
 16namespace Api.Works.Queries;
 17
 18[QueryType]
 19public static partial class WorkQuery
 20{
 21    [PermissionCheckAuthorize(UserPermissionBits.WorkRead)]
 22    [UseFiltering]
 23    [UseSorting]
 24    public static async Task<PageConnection<Work>> GetWorks(
 25        [Service] PGContext db,
 26        [Service] ICurrentUserId userId,
 27        [Service] IWorkByIdDataLoader workById,
 28        QueryContext<Work> qc,
 29        PagingArguments pagingArguments,
 30        CancellationToken ct
 31    )
 132    {
 133        return await db
 134            .Works.Where(w => w.OwnerId == userId.Id)
 135            .ProjectToDto()
 136            .WithQueryContext(qc)
 137            .ToPageWithDataLoaderAsync(pagingArguments, workById, ct);
 138    }
 39}
 40
 41[ObjectType<Work>]
 42public static partial class WorkNode
 43{
 44    [PermissionCheckAuthorize(
 45        UserPermissionBits.AuthorRead | UserPermissionBits.WorkRead
 46    )]
 47    [GraphQLName("Authors")]
 48    public static async Task<IReadOnlyList<Author>> GetAuthorsByWorkAsync(
 49        [Parent] Work work,
 50        IAuthorIdByWorkIdDataLoader authorIdLoader,
 51        IAuthorByIdDataLoader authorLoader,
 52        CancellationToken ct
 53    )
 54    {
 55        var ids = await authorIdLoader.LoadAsync(work.Id, ct);
 56        ids ??= [];
 57        return (await authorLoader.LoadAsync(ids, ct))!;
 58    }
 59
 60    [PermissionCheckAuthorize(UserPermissionBits.TagRead | UserPermissionBits.WorkRead)]
 61    [GraphQLName("Tags")]
 62    public static async Task<IReadOnlyList<Tag>> GetTagsByWorkAsync(
 63        [Parent] Work work,
 64        ITagIdsByWorkIdDataLoader tagIdsByWorkLoader,
 65        TagNode.ITagByIdDataLoader tagByIdLoader,
 66        int? limit,
 67        CancellationToken ct
 68    )
 69    {
 70        var ids = await tagIdsByWorkLoader.LoadAsync(work.Id, ct);
 71        if (limit is not null)
 72        {
 73            ids = [.. ids?.Take((int)limit) ?? []];
 74        }
 75        ids ??= [];
 76        return (await tagByIdLoader.LoadAsync(ids, ct))!;
 77    }
 78
 79    [PermissionCheckAuthorize(UserPermissionBits.WorkRead)]
 80    [GraphQLIgnore]
 81    public static async Task<Work?> GetByIdAsync(
 82        [Service] IWorkByIdDataLoader workById,
 83        Guid id,
 84        CancellationToken ct
 85    ) => await workById.LoadAsync(id, cancellationToken: ct);
 86}
 87
 88public static class WorkDataLoaders
 89{
 90    public interface ITagIdsByWorkIdDataLoader : IBatchDataLoader<Guid, Guid[]>;
 91
 92    [GraphQLIgnore]
 93    [DataLoader<ITagIdsByWorkIdDataLoader>]
 94    public static async Task<IDictionary<Guid, Guid[]>> GetTagIdsByWorkIdAsync(
 95        IReadOnlyList<Guid> ids,
 96        [Service] PGContext db,
 97        [Service] ICurrentUserId userId,
 98        CancellationToken ct
 99    ) =>
 100        await db.Works.GetManyToManyIds(
 101            ids,
 102            (Guid)userId.Id!,
 103            w => w.WorkTag_Works.Select(wt => wt.WorkTagId),
 104            ct
 105        );
 106
 107    public interface IAuthorIdByWorkIdDataLoader : IBatchDataLoader<Guid, Guid[]>;
 108
 109    [GraphQLIgnore]
 110    [DataLoader<IAuthorIdByWorkIdDataLoader>]
 111    public static async Task<IDictionary<Guid, Guid[]>> GetAuthorIdByWorkIdAsync(
 112        IReadOnlyList<Guid> ids,
 113        [Service] PGContext db,
 114        [Service] ICurrentUserId userId,
 115        CancellationToken ct
 116    ) =>
 117        await db.Works.GetManyToManyIds(
 118            ids,
 119            (Guid)userId.Id!,
 120            w => w.Work_Authors.Select(wa => wa.AuthorId),
 121            ct
 122        );
 123
 124    public interface IWorkByIdDataLoader : IBatchDataLoader<Guid, Work>;
 125
 126    [GraphQLIgnore]
 127    [DataLoader<IWorkByIdDataLoader>]
 128    public static async Task<IDictionary<Guid, Work>> GetWorkByIdAsync(
 129        IReadOnlyList<Guid> ids,
 130        [Service] PGContext db,
 131        [Service] ICurrentUserId userId,
 132        CancellationToken ct
 133    )
 134    {
 135        return await db
 136            .Works.Where(w => w.OwnerId == userId.Id)
 137            .Where(w => ids.Contains(w.Id))
 138            .ProjectToDto()
 139            .ToDictionaryAsync(w => w.Id, cancellationToken: ct);
 140    }
 141}
 142
 143[Node(NodeResolverType = typeof(WorkNode), NodeResolver = nameof(WorkNode.GetByIdAsync))]
 144public class Work : IEntityMetadata, INode
 145{
 146    public static byte IdPostfix => Models.Work.IdPostfix;
 147
 148    public Guid Id { get; set; }
 149    public int RowVersion { get; set; }
 150    public NodaTime.Instant MetadataAddedAt { get; set; }
 151    public NodaTime.Instant MetadataUpdatedAt { get; set; }
 152
 153    public required string Title { get; set; }
 154
 155    public string? Description { get; set; }
 156
 157    public NodaTime.Instant? WorkPublishedAt { get; set; }
 158    public NodaTime.Instant? WorkUpdatedAt { get; set; }
 159    public List<WorkIdentifier> WorkIdentifiers { get; set; } = [];
 160}
 161
 162public record WorkIdentifier(string WorkIdentifierType, string WorkIdentifierValue);
 163
 164[Mapper]
 165public static partial class WorkMapper
 166{
 167    public static partial Models.WorkIdentifier FromWorkIdDto(WorkIdentifier w);
 168
 169    public static partial Work? ToDto(Models.Work? w);
 170
 171    public static partial IQueryable<Work> ProjectToDto(this IQueryable<Models.Work> q);
 172}