diff --git a/.build/Build.Environment.cs b/.build/Build.Environment.cs index 09ebfeb46be..a3a82e18a69 100644 --- a/.build/Build.Environment.cs +++ b/.build/Build.Environment.cs @@ -15,7 +15,6 @@ partial class Build AbsolutePath SonarSolutionFile => SourceDirectory / "Build.Sonar.sln"; AbsolutePath TestSolutionFile => TemporaryDirectory / "Build.Test.sln"; AbsolutePath PackSolutionFile => SourceDirectory / "Build.Pack.sln"; - AbsolutePath SgSolutionFile => SourceDirectory / "StrawberryShake" / "SourceGenerator" / "StrawberryShake.SourceGenerator.sln"; AbsolutePath OutputDirectory => RootDirectory / "output"; AbsolutePath TestResultDirectory => OutputDirectory / "test-results"; diff --git a/.build/Build.Publish.cs b/.build/Build.Publish.cs index b5a25c6c806..9e866597fac 100644 --- a/.build/Build.Publish.cs +++ b/.build/Build.Publish.cs @@ -26,8 +26,7 @@ partial class Build .Requires(() => Configuration.Equals(Release)) .Executes(() => { - var packages = PackageDirectory.GlobFiles("HotChocolate.*.nupkg") - .Concat(PackageDirectory.GlobFiles("GreenDonut.*.nupkg")); + var packages = PackageDirectory.GlobFiles("*.*.nupkg"); DotNetNuGetPush( _ => _ @@ -66,26 +65,6 @@ partial class Build DotNetRestore(c => c.SetProjectFile(PackSolutionFile)); - DotNetBuild(c => c - .SetNoRestore(true) - .SetProjectFile(RootDirectory / "src/StrawberryShake/CodeGeneration/src/CodeGeneration.CSharp.Server/StrawberryShake.CodeGeneration.CSharp.Server.csproj") - .SetOutputDirectory(RootDirectory / "src/StrawberryShake/Tooling/src/.server") - .SetConfiguration(Configuration) - .SetAssemblyVersion(GitVersion.AssemblySemVer) - .SetFileVersion(GitVersion.AssemblySemFileVer) - .SetInformationalVersion(GitVersion.InformationalVersion) - .SetVersion(GitVersion.SemVer)); - - DotNetBuild(c => c - .SetNoRestore(true) - .SetProjectFile(RootDirectory / "src/StrawberryShake/CodeGeneration/src/CodeGeneration.CSharp.Server/StrawberryShake.CodeGeneration.CSharp.Server.csproj") - .SetOutputDirectory(RootDirectory / "src/StrawberryShake/SourceGenerator/src/.server") - .SetConfiguration(Configuration) - .SetAssemblyVersion(GitVersion.AssemblySemVer) - .SetFileVersion(GitVersion.AssemblySemFileVer) - .SetInformationalVersion(GitVersion.InformationalVersion) - .SetVersion(GitVersion.SemVer)); - DotNetBuild(c => c .SetNoRestore(true) .SetProjectFile(PackSolutionFile) @@ -124,8 +103,7 @@ partial class Build .Requires(() => Configuration.Equals(Release)) .Executes(() => { - var packages = PackageDirectory.GlobFiles("HotChocolate.*.nupkg") - .Concat(PackageDirectory.GlobFiles("GreenDonut.*.nupkg")); + var packages = PackageDirectory.GlobFiles("*.*.nupkg"); DotNetNuGetPush( _ => _ diff --git a/.build/Build.Sonar.cs b/.build/Build.Sonar.cs index 220df88541d..ea5de7909cf 100644 --- a/.build/Build.Sonar.cs +++ b/.build/Build.Sonar.cs @@ -35,8 +35,6 @@ partial class Build SonarScannerBegin(SonarBeginPrSettings); - BuildCodeGenServer(); - DotNetBuild(SonarBuildAll); try @@ -65,8 +63,6 @@ partial class Build SonarScannerBegin(SonarBeginFullSettings); - BuildCodeGenServer(); - DotNetBuild(SonarBuildAll); try diff --git a/.build/Build.Tests.2.cs b/.build/Build.Tests.2.cs index 30c21f06fd8..80137d5a262 100644 --- a/.build/Build.Tests.2.cs +++ b/.build/Build.Tests.2.cs @@ -87,17 +87,12 @@ partial class Build .Produces(TestResultDirectory / "*.trx") .Executes(() => RunTests(SourceDirectory / "StrawberryShake" / "CodeGeneration" / "StrawberryShake.CodeGeneration.sln")); - Target TestStrawberryShakeSourceGenerator => _ => _ - .Produces(TestResultDirectory / "*.trx") - .Executes(() => RunClientTests(SourceDirectory / "StrawberryShake" / "SourceGenerator" / "StrawberryShake.SourceGenerator.sln")); - Target TestStrawberryShakeTooling => _ => _ .Produces(TestResultDirectory / "*.trx") .Executes(() => RunClientTests(SourceDirectory / "StrawberryShake" / "Tooling" / "StrawberryShake.Tooling.sln")); void RunClientTests(AbsolutePath solutionFile) { - BuildCodeGenServer(true); RunTests(solutionFile); } diff --git a/.build/Build.Tests.cs b/.build/Build.Tests.cs index 5c989d5b1d7..6f798445ced 100644 --- a/.build/Build.Tests.cs +++ b/.build/Build.Tests.cs @@ -69,7 +69,6 @@ partial class Build TestHotChocolateUtilities, TestStrawberryShakeClient, TestStrawberryShakeCodeGeneration, - TestStrawberryShakeSourceGenerator, TestStrawberryShakeTooling); Target Cover => _ => _ diff --git a/.build/Build.cs b/.build/Build.cs index 857041aea97..945b9ee51a0 100644 --- a/.build/Build.cs +++ b/.build/Build.cs @@ -1,7 +1,6 @@ using Nuke.Common; using Nuke.Common.CI; using Nuke.Common.CI.AzurePipelines; -using Nuke.Common.CI.GitHubActions; using Nuke.Common.Execution; using Nuke.Common.Tools.DotNet; using static Nuke.Common.Tools.DotNet.DotNetTasks; @@ -29,7 +28,6 @@ partial class Build : NukeBuild { DotNetBuildSonarSolution(AllSolutionFile); DotNetRestore(c => c.SetProjectFile(AllSolutionFile)); - BuildCodeGenServer(); }); Target Compile => _ => _ @@ -62,19 +60,4 @@ partial class Build : NukeBuild DotNetBuildSonarSolution(AllSolutionFile); DotNetRestore(c => c.SetProjectFile(AllSolutionFile)); }); - - void BuildCodeGenServer(bool restore = false) - { - DotNetBuild(c => c - .SetNoRestore(!restore) - .SetProjectFile(RootDirectory / "src/StrawberryShake/CodeGeneration/src/CodeGeneration.CSharp.Server/StrawberryShake.CodeGeneration.CSharp.Server.csproj") - .SetOutputDirectory(RootDirectory / "src/StrawberryShake/Tooling/src/.server") - .SetConfiguration(Configuration)); - - DotNetBuild(c => c - .SetNoRestore(!restore) - .SetProjectFile(RootDirectory / "src/StrawberryShake/CodeGeneration/src/CodeGeneration.CSharp.Server/StrawberryShake.CodeGeneration.CSharp.Server.csproj") - .SetOutputDirectory(RootDirectory / "src/StrawberryShake/SourceGenerator/src/.server") - .SetConfiguration(Configuration)); - } } diff --git a/.build/Helpers.cs b/.build/Helpers.cs index d6574a7f3e0..066dbdd5bd3 100644 --- a/.build/Helpers.cs +++ b/.build/Helpers.cs @@ -30,7 +30,7 @@ static class Helpers Path.Combine("HotChocolate", "Spatial"), Path.Combine("StrawberryShake", "Client"), Path.Combine("StrawberryShake", "CodeGeneration"), - Path.Combine("StrawberryShake", "SourceGenerator"), + Path.Combine("StrawberryShake", "MetaPackages"), Path.Combine("StrawberryShake", "Tooling"), "CookieCrumble" }; diff --git a/.devops/azure-pipelines.release-hotchocolate.yml b/.devops/azure-pipelines.release-hotchocolate.yml index 022acf62ae0..020d2885e7c 100644 --- a/.devops/azure-pipelines.release-hotchocolate.yml +++ b/.devops/azure-pipelines.release-hotchocolate.yml @@ -247,18 +247,6 @@ stages: inputs: artifactName: test-results pathtoPublish: "output/test-results" - - job: TestStrawberryShakeSourceGenerator - displayName: src/StrawberryShake/SourceGenerator - steps: - - task: CmdLine@2 - displayName: "Run Tests" - inputs: - script: "./build.cmd TestStrawberryShakeSourceGenerator --skip --test-partition $(System.JobPositionInPhase)" - - task: PublishBuildArtifacts@1 - displayName: "Upload Test Results" - inputs: - artifactName: test-results - pathtoPublish: "output/test-results" - job: TestStrawberryShakeTooling displayName: src/StrawberryShake/Tooling steps: diff --git a/.devops/azure-pipelines.test-pr-hotchocolate.yml b/.devops/azure-pipelines.test-pr-hotchocolate.yml index 4cf24fa3a57..f1cf4e9774c 100644 --- a/.devops/azure-pipelines.test-pr-hotchocolate.yml +++ b/.devops/azure-pipelines.test-pr-hotchocolate.yml @@ -133,6 +133,18 @@ stages: inputs: artifactName: test-results pathtoPublish: "output/test-results" + - job: TestHotChocolateFusion + displayName: src/HotChocolate/Fusion + steps: + - task: CmdLine@2 + displayName: "Run Tests" + inputs: + script: "./build.cmd TestHotChocolateFusion --skip --test-partition $(System.JobPositionInPhase)" + - task: PublishBuildArtifacts@1 + displayName: "Upload Test Results" + inputs: + artifactName: test-results + pathtoPublish: "output/test-results" - job: TestHotChocolateLanguage displayName: src/HotChocolate/Language steps: @@ -241,18 +253,6 @@ stages: inputs: artifactName: test-results pathtoPublish: "output/test-results" - - job: TestStrawberryShakeSourceGenerator - displayName: src/StrawberryShake/SourceGenerator - steps: - - task: CmdLine@2 - displayName: "Run Tests" - inputs: - script: "./build.cmd TestStrawberryShakeSourceGenerator --skip --test-partition $(System.JobPositionInPhase)" - - task: PublishBuildArtifacts@1 - displayName: "Upload Test Results" - inputs: - artifactName: test-results - pathtoPublish: "output/test-results" - job: TestStrawberryShakeTooling displayName: src/StrawberryShake/Tooling steps: diff --git a/src/HotChocolate/Core/src/Execution/Processing/DirectiveCollectionExtensions.cs b/src/HotChocolate/Core/src/Execution/Processing/DirectiveCollectionExtensions.cs index 2ed36b2e910..6dc6156eb82 100644 --- a/src/HotChocolate/Core/src/Execution/Processing/DirectiveCollectionExtensions.cs +++ b/src/HotChocolate/Core/src/Execution/Processing/DirectiveCollectionExtensions.cs @@ -3,6 +3,7 @@ using HotChocolate.Language; using HotChocolate.Types; using HotChocolate.Utilities; +using IHasDirectives = HotChocolate.Language.IHasDirectives; namespace HotChocolate.Execution.Processing; @@ -64,6 +65,10 @@ private static IValueNode GetIfArgumentValue(DirectiveNode directive) this IReadOnlyList directives) => GetDirective(directives, WellKnownDirectives.Include); + internal static DirectiveNode? GetDeferDirective( + this IHasDirectives container) => + GetDirective(container.Directives, WellKnownDirectives.Defer); + internal static DeferDirective? GetDeferDirective( this IReadOnlyList directives, IVariableValueCollection variables) diff --git a/src/StrawberryShake/Client/src/MetaPackage/StrawberryShake.csproj b/src/StrawberryShake/Client/src/MetaPackage/StrawberryShake.csproj index be30f128a2d..396c1bcdebe 100644 --- a/src/StrawberryShake/Client/src/MetaPackage/StrawberryShake.csproj +++ b/src/StrawberryShake/Client/src/MetaPackage/StrawberryShake.csproj @@ -11,7 +11,6 @@ - diff --git a/src/StrawberryShake/Client/src/Razor/UseQuery.cs b/src/StrawberryShake/Client/src/Razor/UseQuery.cs index 01f6b5485ed..2eacb5cb571 100644 --- a/src/StrawberryShake/Client/src/Razor/UseQuery.cs +++ b/src/StrawberryShake/Client/src/Razor/UseQuery.cs @@ -8,7 +8,7 @@ namespace StrawberryShake.Razor; public abstract class UseQuery : ComponentBase, IDisposable where TResult : class { private IDisposable? _subscription; - private bool _isLoading = true; + private bool _isInitializing = true; private bool _isErrorResult; private bool _isSuccessResult; private TResult? _result; @@ -27,20 +27,21 @@ protected void Subscribe(IObservable> observable) { _subscription?.Dispose(); - _subscription = observable.Subscribe(operationResult => - { - _result = operationResult.Data; - _errors = operationResult.Errors; - _isErrorResult = operationResult.IsErrorResult(); - _isSuccessResult = operationResult.IsSuccessResult(); - _isLoading = false; - StateHasChanged(); - }); + _subscription = observable + .Subscribe(operationResult => + { + _result = operationResult.Data; + _errors = operationResult.Errors; + _isErrorResult = operationResult.IsErrorResult(); + _isSuccessResult = operationResult.IsSuccessResult(); + _isInitializing = false; + StateHasChanged(); + }); } protected override void BuildRenderTree(RenderTreeBuilder builder) { - if (_isLoading && LoadingContent is not null) + if (_isInitializing && LoadingContent is not null) { builder.AddContent(0, LoadingContent); } diff --git a/src/StrawberryShake/Client/src/Razor/UseSubscription.cs b/src/StrawberryShake/Client/src/Razor/UseSubscription.cs new file mode 100644 index 00000000000..73acc42377f --- /dev/null +++ b/src/StrawberryShake/Client/src/Razor/UseSubscription.cs @@ -0,0 +1,78 @@ +using System; +using System.Collections.Generic; +using Microsoft.AspNetCore.Components; +using Microsoft.AspNetCore.Components.Rendering; + +namespace StrawberryShake.Razor; + +public abstract class UseSubscription : ComponentBase, IDisposable where TResult : class +{ + private IDisposable? _subscription; + private bool _isInitializing = true; + private bool _isErrorResult; + private bool _isSuccessResult; + private TResult? _result; + private IReadOnlyList? _errors; + private bool _disposed; + + [Parameter] public RenderFragment? ChildContent { get; set; } + + [Parameter] public RenderFragment>? ErrorContent { get; set; } + + [Parameter] public RenderFragment? LoadingContent { get; set; } + + protected void Subscribe(IObservable> observable) + { + _subscription?.Dispose(); + + _subscription = observable + .Subscribe(operationResult => + { + _result = operationResult.Data; + _errors = operationResult.Errors; + _isErrorResult = operationResult.IsErrorResult(); + _isSuccessResult = operationResult.IsSuccessResult(); + _isInitializing = false; + StateHasChanged(); + }); + } + + protected override void BuildRenderTree(RenderTreeBuilder builder) + { + if (_isInitializing && LoadingContent is not null) + { + builder.AddContent(0, LoadingContent); + } + + if (_isErrorResult) + { + builder.AddContent(0, ErrorContent, _errors!); + } + + if (_isSuccessResult) + { + builder.AddContent(0, ChildContent, _result!); + } + + base.BuildRenderTree(builder); + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + protected virtual void Dispose(bool disposing) + { + if (!_disposed) + { + if (disposing) + { + _subscription?.Dispose(); + } + + _disposed = true; + } + } +} diff --git a/src/StrawberryShake/CodeGeneration/src/CodeGeneration.CSharp.Server/CSharpGeneratorServer.Generate.cs b/src/StrawberryShake/CodeGeneration/src/CodeGeneration.CSharp.Server/CSharpGeneratorServer.Generate.cs index e7720a21ba5..9924d6b7c33 100644 --- a/src/StrawberryShake/CodeGeneration/src/CodeGeneration.CSharp.Server/CSharpGeneratorServer.Generate.cs +++ b/src/StrawberryShake/CodeGeneration/src/CodeGeneration.CSharp.Server/CSharpGeneratorServer.Generate.cs @@ -6,13 +6,15 @@ using System.Text; using System.Text.Json; using System.Threading.Tasks; -using DotNet.Globbing; +using GlobExpressions; using HotChocolate; using HotChocolate.Language; using HotChocolate.Utilities; using StrawberryShake.Tools.Configuration; using static System.IO.Path; using static StrawberryShake.CodeGeneration.CSharp.ErrorHelper; +using static StrawberryShake.CodeGeneration.CSharp.ServerResources; +using Path = System.IO.Path; namespace StrawberryShake.CodeGeneration.CSharp; @@ -24,8 +26,8 @@ private static async Task GenerateAsync(GeneratorRequest requ { try { - CSharpGeneratorServerSettings settings = await LoadSettingsAsync(request); - IReadOnlyList documents = GetMatchingDocuments(request, settings); + var settings = await LoadSettingsAsync(request); + var documents = GetMatchingDocuments(request, settings); if (settings.RequestStrategy == RequestStrategy.PersistedQuery) { @@ -35,7 +37,7 @@ private static async Task GenerateAsync(GeneratorRequest requ } } - CSharpGeneratorResult result = CSharpGenerator.Generate(documents, settings); + var result = CSharpGenerator.Generate(documents, settings); await TryWriteCSharpFilesAsync(result.Documents, settings); await TryWriteRazorFilesAsync(result.Documents, settings); @@ -78,7 +80,7 @@ private static async Task GenerateAsync(GeneratorRequest requ var generatedFiles = new HashSet(); - foreach (SourceDocument document in + foreach (var document in documents.Where(t => t.Kind is SourceDocumentKind.CSharp)) { var fileName = Combine(generatedDirectory, $"{document.Name}.g.cs"); @@ -129,7 +131,7 @@ private static async Task GenerateAsync(GeneratorRequest requ var generatedFiles = new HashSet(); - foreach (SourceDocument document in + foreach (var document in documents.Where(t => t.Kind is SourceDocumentKind.Razor)) { var fileName = Combine(generatedDirectory, $"{document.Name}.components.g.cs"); @@ -177,7 +179,7 @@ private static async Task GenerateAsync(GeneratorRequest requ ClearPersistedQueryDirectory(persistedQueryDirectory); - foreach (SourceDocument document in + foreach (var document in documents.Where(t => t.Kind is SourceDocumentKind.GraphQL)) { var fileName = Combine(persistedQueryDirectory, $"{document.Name}.graphql"); @@ -210,7 +212,7 @@ private static async Task GenerateAsync(GeneratorRequest requ var files = new Dictionary(); - foreach (SourceDocument document in + foreach (var document in documents.Where(t => t.Kind is SourceDocumentKind.GraphQL)) { var hash = BitConverter.ToString(ComputeHash(document)).Replace("-", ""); @@ -230,9 +232,9 @@ private static async Task GenerateAsync(GeneratorRequest requ var json = await File.ReadAllTextAsync(request.ConfigFileName); var config = GraphQLConfig.FromJson(json); - if (!NameUtils.IsValidGraphQLName(config.Extensions.StrawberryShake.Name)) + if (!config.Extensions.StrawberryShake.Name.IsValidGraphQLName()) { - throw new GraphQLException(ServerResources.CSharpGeneratorServer_ClientName_Invalid); + throw new GraphQLException(CSharpGeneratorServer_ClientName_Invalid); } var generatorSettings = new CSharpGeneratorServerSettings @@ -244,22 +246,25 @@ private static async Task GenerateAsync(GeneratorRequest requ request.DefaultNamespace ?? "StrawberryShake.Generated", RequestStrategy = config.Extensions.StrawberryShake.RequestStrategy, - StrictSchemaValidation = config.Extensions.StrawberryShake.StrictSchemaValidation, - NoStore = config.Extensions.StrawberryShake.NoStore, + StrictSchemaValidation = + config.Extensions.StrawberryShake.StrictSchemaValidation + ?? true, + NoStore = config.Extensions.StrawberryShake.NoStore ?? true, InputRecords = config.Extensions.StrawberryShake.Records.Inputs, - RazorComponents = config.Extensions.StrawberryShake.RazorComponents, + RazorComponents = config.Extensions.StrawberryShake.RazorComponents ?? false, EntityRecords = config.Extensions.StrawberryShake.Records.Entities, - SingleCodeFile = config.Extensions.StrawberryShake.UseSingleFile, + SingleCodeFile = config.Extensions.StrawberryShake.UseSingleFile ?? true, Documents = config.Documents, PersistedQueryDirectory = request.PersistedQueryDirectory, - HashProvider = config.Extensions.StrawberryShake.HashAlgorithm.ToLowerInvariant() - switch - { - "sha1" => new Sha1DocumentHashProvider(HashFormat.Hex), - "sha256" => new Sha256DocumentHashProvider(HashFormat.Hex), - "md5" => new MD5DocumentHashProvider(HashFormat.Hex), - _ => new Sha1DocumentHashProvider(HashFormat.Hex) - }, + HashProvider = + (config.Extensions.StrawberryShake.HashAlgorithm?.ToLowerInvariant() ?? "md5") + switch + { + "sha1" => new Sha1DocumentHashProvider(HashFormat.Hex), + "sha256" => new Sha256DocumentHashProvider(HashFormat.Hex), + "md5" => new MD5DocumentHashProvider(HashFormat.Hex), + _ => new Sha1DocumentHashProvider(HashFormat.Hex) + }, Option = request.Option }; @@ -269,7 +274,7 @@ private static async Task GenerateAsync(GeneratorRequest requ { generatorSettings.TransportProfiles.Clear(); - foreach (StrawberryShakeSettingsTransportProfile profile in profiles) + foreach (var profile in profiles) { generatorSettings.TransportProfiles.Add( new TransportProfile( @@ -316,13 +321,13 @@ private static async Task GenerateAsync(GeneratorRequest requ GeneratorRequest request, CSharpGeneratorServerSettings settings) { - var rootDirectory = request.RootDirectory + DirectorySeparatorChar; + var rootDirectory = request.RootDirectory; - var glob = Glob.Parse(settings.Documents); + var files = Glob.Files(rootDirectory, settings.Documents) + .Select(t => Combine(rootDirectory, t)) + .ToArray(); - return request.DocumentFileNames - .Where(t => t.StartsWith(rootDirectory) && glob.IsMatch(t)) - .ToList(); + return files; } private static GeneratorResponse CreateResponse( @@ -331,7 +336,7 @@ private static async Task GenerateAsync(GeneratorRequest requ { var generatorDocuments = new List(); - foreach (SourceDocument sourceDocument in sourceDocuments) + foreach (var sourceDocument in sourceDocuments) { generatorDocuments.Add( new GeneratorDocument( @@ -366,7 +371,7 @@ private static bool Compare(string fileName, SourceDocument document) private static byte[] ComputeHash(string fileName) { - using FileStream stream = File.OpenRead(fileName); + using var stream = File.OpenRead(fileName); return _sha256.ComputeHash(stream); } diff --git a/src/StrawberryShake/CodeGeneration/src/CodeGeneration.CSharp.Server/CSharpGeneratorServer.cs b/src/StrawberryShake/CodeGeneration/src/CodeGeneration.CSharp.Server/CSharpGeneratorServer.cs index 51a8737340d..081b801fadc 100644 --- a/src/StrawberryShake/CodeGeneration/src/CodeGeneration.CSharp.Server/CSharpGeneratorServer.cs +++ b/src/StrawberryShake/CodeGeneration/src/CodeGeneration.CSharp.Server/CSharpGeneratorServer.cs @@ -25,8 +25,8 @@ private static async Task ProcessAsync(string fileSink) { try { - GeneratorRequest request = RequestFormatter.Take(fileSink); - GeneratorResponse response = await GenerateAsync(request); + var request = RequestFormatter.Take(fileSink); + var response = await GenerateAsync(request); ResponseFormatter.Format(response, fileSink); return 0; } diff --git a/src/StrawberryShake/CodeGeneration/src/CodeGeneration.CSharp.Server/ErrorHelper.cs b/src/StrawberryShake/CodeGeneration/src/CodeGeneration.CSharp.Server/ErrorHelper.cs index a6a15c8a2c6..3b2c3d7328f 100644 --- a/src/StrawberryShake/CodeGeneration/src/CodeGeneration.CSharp.Server/ErrorHelper.cs +++ b/src/StrawberryShake/CodeGeneration/src/CodeGeneration.CSharp.Server/ErrorHelper.cs @@ -50,7 +50,7 @@ private static GeneratorError ConvertError(IError error) private static Location ConvertLocation(IEnumerable locations) { - HotChocolate.Location loc = locations.First(); + var loc = locations.First(); return new Location(loc.Line, loc.Column); } diff --git a/src/StrawberryShake/CodeGeneration/src/CodeGeneration.CSharp.Server/StrawberryShake.CodeGeneration.CSharp.Server.csproj b/src/StrawberryShake/CodeGeneration/src/CodeGeneration.CSharp.Server/StrawberryShake.CodeGeneration.CSharp.Server.csproj index f32ef3c3eae..35920859972 100644 --- a/src/StrawberryShake/CodeGeneration/src/CodeGeneration.CSharp.Server/StrawberryShake.CodeGeneration.CSharp.Server.csproj +++ b/src/StrawberryShake/CodeGeneration/src/CodeGeneration.CSharp.Server/StrawberryShake.CodeGeneration.CSharp.Server.csproj @@ -11,11 +11,7 @@ Exe enable - - - - - + @@ -33,5 +29,9 @@ ServerResources.resx + + + + diff --git a/src/StrawberryShake/CodeGeneration/src/CodeGeneration.CSharp/CSharpGenerator.cs b/src/StrawberryShake/CodeGeneration/src/CodeGeneration.CSharp/CSharpGenerator.cs index 0bfeb975fcf..2d532bdd69c 100644 --- a/src/StrawberryShake/CodeGeneration/src/CodeGeneration.CSharp/CSharpGenerator.cs +++ b/src/StrawberryShake/CodeGeneration/src/CodeGeneration.CSharp/CSharpGenerator.cs @@ -53,6 +53,7 @@ public static class CSharpGenerator new InputTypeStateInterfaceGenerator(), new ResultInterfaceGenerator(), new DataTypeGenerator(), + new RazorQueryGenerator(), new RazorQueryGenerator() }; diff --git a/src/StrawberryShake/CodeGeneration/src/CodeGeneration.CSharp/Generators/RazorSubscriptionGenerator.cs b/src/StrawberryShake/CodeGeneration/src/CodeGeneration.CSharp/Generators/RazorSubscriptionGenerator.cs new file mode 100644 index 00000000000..8b886cb224e --- /dev/null +++ b/src/StrawberryShake/CodeGeneration/src/CodeGeneration.CSharp/Generators/RazorSubscriptionGenerator.cs @@ -0,0 +1,130 @@ +using System.Collections.Generic; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using StrawberryShake.CodeGeneration.CSharp.Extensions; +using StrawberryShake.CodeGeneration.Descriptors.Operations; +using StrawberryShake.CodeGeneration.Descriptors.TypeDescriptors; +using StrawberryShake.CodeGeneration.Extensions; +using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; +using static StrawberryShake.CodeGeneration.Utilities.NameUtils; + +namespace StrawberryShake.CodeGeneration.CSharp.Generators; + +public class RazorSubscriptionGenerator : CSharpSyntaxGenerator +{ + protected override bool CanHandle( + OperationDescriptor descriptor, + CSharpSyntaxGeneratorSettings settings) => + settings.RazorComponents && descriptor is SubscriptionOperationDescriptor; + + protected override CSharpSyntaxGeneratorResult Generate( + OperationDescriptor descriptor, + CSharpSyntaxGeneratorSettings settings) + { + var componentName = $"Use{descriptor.Name}"; + var resultType = descriptor.ResultTypeReference.GetRuntimeType().ToString(); + + var classDeclaration = + ClassDeclaration(componentName) + .AddImplements(TypeNames.UseSubscription.WithGeneric(resultType)) + .AddModifiers( + Token(SyntaxKind.PublicKeyword), + Token(SyntaxKind.PartialKeyword)) + .AddGeneratedAttribute() + .AddMembers(CreateOperationProperty(descriptor.RuntimeType.ToString())); + + foreach (var argument in descriptor.Arguments) + { + classDeclaration = classDeclaration.AddMembers( + CreateArgumentProperty(argument)); + } + + classDeclaration = classDeclaration.AddMembers( + CreateLifecycleMethodMethod("OnInitialized", descriptor.Arguments)); + classDeclaration = classDeclaration.AddMembers( + CreateLifecycleMethodMethod("OnParametersSet", descriptor.Arguments)); + + return new CSharpSyntaxGeneratorResult( + componentName, + Components, + $"{descriptor.RuntimeType.NamespaceWithoutGlobal}.{Components}", + classDeclaration, + isRazorComponent: true); + } + + private PropertyDeclarationSyntax CreateOperationProperty(string typeName) => + PropertyDeclaration(ParseTypeName(typeName), "Operation") + .WithAttributeLists( + SingletonList( + AttributeList( + SingletonSeparatedList( + Attribute( + IdentifierName(TypeNames.InjectAttribute)))))) + .AddModifiers(Token(SyntaxKind.InternalKeyword)) + .WithGetterAndSetter() + .WithSuppressNullableWarningExpression(); + + private PropertyDeclarationSyntax CreateArgumentProperty(PropertyDescriptor property) + { + var propertySyntax = + PropertyDeclaration(property.Type.ToTypeSyntax(), GetPropertyName(property.Name)) + .WithAttributeLists( + SingletonList( + AttributeList( + SingletonSeparatedList( + Attribute( + IdentifierName(TypeNames.ParameterAttribute)))))) + .AddModifiers(Token(SyntaxKind.PublicKeyword)) + .WithGetterAndSetter(); + + if (property.Type.IsNonNull()) + { + propertySyntax = propertySyntax.WithSuppressNullableWarningExpression(); + } + + return propertySyntax; + } + + private MethodDeclarationSyntax CreateLifecycleMethodMethod( + string methodName, + IReadOnlyList arguments) + { + var argumentList = new List(); + + foreach (var argument in arguments) + { + argumentList.Add(Argument(IdentifierName(GetPropertyName(argument.Name)))); + } + + var invocation = InvocationExpression( + MemberAccessExpression( + SyntaxKind.SimpleMemberAccessExpression, + IdentifierName("Operation"), + IdentifierName("Watch"))); + + if (argumentList.Count > 0) + { + invocation = invocation.WithArgumentList(ArgumentList(SeparatedList(argumentList))); + } + + var bodyStatements = + SingletonList( + ExpressionStatement( + InvocationExpression( + IdentifierName("Subscribe")) + .WithArgumentList( + ArgumentList( + SingletonSeparatedList( + Argument(invocation)))))); + + return MethodDeclaration( + PredefinedType(Token(SyntaxKind.VoidKeyword)), + Identifier(methodName)) + .WithModifiers( + TokenList( + Token(SyntaxKind.ProtectedKeyword), + Token(SyntaxKind.OverrideKeyword))) + .WithBody(Block(bodyStatements)); + } +} diff --git a/src/StrawberryShake/CodeGeneration/src/CodeGeneration/TypeNames.cs b/src/StrawberryShake/CodeGeneration/src/CodeGeneration/TypeNames.cs index f5d967428f4..0c51c117d67 100644 --- a/src/StrawberryShake/CodeGeneration/src/CodeGeneration/TypeNames.cs +++ b/src/StrawberryShake/CodeGeneration/src/CodeGeneration/TypeNames.cs @@ -237,6 +237,9 @@ public static class TypeNames public const string UseQuery = StrawberryShakeNamespace + "Razor." + nameof(UseQuery); + public const string UseSubscription = + StrawberryShakeNamespace + "Razor." + nameof(UseSubscription); + public const string Upload = StrawberryShakeNamespace + nameof(Upload); public const string StringSerializer = diff --git a/src/StrawberryShake/CodeGeneration/src/Directory.Build.props b/src/StrawberryShake/CodeGeneration/src/Directory.Build.props index cc41f4210f2..bf0bb158c44 100644 --- a/src/StrawberryShake/CodeGeneration/src/Directory.Build.props +++ b/src/StrawberryShake/CodeGeneration/src/Directory.Build.props @@ -2,7 +2,7 @@ - net6.0 + $(ToolingTargetFrameworks) $(NoWarn);CA1812 diff --git a/src/StrawberryShake/Directory.Build.props b/src/StrawberryShake/Directory.Build.props index 14ffa7e0781..1ffaa240f96 100644 --- a/src/StrawberryShake/Directory.Build.props +++ b/src/StrawberryShake/Directory.Build.props @@ -16,7 +16,7 @@ net7.0; net6.0 net7.0; net6.0; net5.0; netcoreapp3.1; netstandard2.1; netstandard2.0 net7.0; net6.0; netstandard2.0 - net7.0; net6.0; net5.0; netcoreapp3.1 + net7.0; net6.0 net7.0; net6.0 diff --git a/src/StrawberryShake/MetaPackages/Blazor/MSBuild/StrawberryShake.Blazor.props b/src/StrawberryShake/MetaPackages/Blazor/MSBuild/StrawberryShake.Blazor.props new file mode 100644 index 00000000000..31bd76b9ee5 --- /dev/null +++ b/src/StrawberryShake/MetaPackages/Blazor/MSBuild/StrawberryShake.Blazor.props @@ -0,0 +1,25 @@ + + + + enable + + enable + + enable + + md5 + + intermediate + + + + + MSBuild:GenerateGraphQLCode + + + + + + + + \ No newline at end of file diff --git a/src/StrawberryShake/MetaPackages/Blazor/MSBuild/StrawberryShake.Blazor.targets b/src/StrawberryShake/MetaPackages/Blazor/MSBuild/StrawberryShake.Blazor.targets new file mode 100644 index 00000000000..92b2818d0ab --- /dev/null +++ b/src/StrawberryShake/MetaPackages/Blazor/MSBuild/StrawberryShake.Blazor.targets @@ -0,0 +1,50 @@ + + + $([System.IO.Path]::Combine($(MSBuildThisFileDirectory), "..", "tools", "dotnet-graphql.dll")) + + + + + + + + + + + GenerateGraphQLCode; + $(CoreCompileDependsOn) + + + + + + $(MSBuildProjectDirectory)\$(IntermediateOutputPath)berry\ + + + + + + + dotnet $(GenTool) generate "$(MSBuildProjectDirectory)" + $(GenCommand) -o "$(GraphQLCodeGenerationRoot)" + $(GenCommand) -n "$(RootNamespace)" + $(GenCommand) -a "$(GraphQLRequestHash)" + $(GenCommand) -s + $(GenCommand) -t + $(GenCommand) -r + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/StrawberryShake/MetaPackages/Blazor/MSBuild/StrawberryShake.MSBuild.ContentType.xaml b/src/StrawberryShake/MetaPackages/Blazor/MSBuild/StrawberryShake.MSBuild.ContentType.xaml new file mode 100644 index 00000000000..feed4021045 --- /dev/null +++ b/src/StrawberryShake/MetaPackages/Blazor/MSBuild/StrawberryShake.MSBuild.ContentType.xaml @@ -0,0 +1,18 @@ + + + + + + + + + + \ No newline at end of file diff --git a/src/StrawberryShake/MetaPackages/Blazor/MSBuild/StrawberryShake.MSBuild.xaml b/src/StrawberryShake/MetaPackages/Blazor/MSBuild/StrawberryShake.MSBuild.xaml new file mode 100644 index 00000000000..f39193142d0 --- /dev/null +++ b/src/StrawberryShake/MetaPackages/Blazor/MSBuild/StrawberryShake.MSBuild.xaml @@ -0,0 +1,19 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/src/StrawberryShake/MetaPackages/Blazor/MSBuild/global.json b/src/StrawberryShake/MetaPackages/Blazor/MSBuild/global.json new file mode 100644 index 00000000000..2f09e06df6b --- /dev/null +++ b/src/StrawberryShake/MetaPackages/Blazor/MSBuild/global.json @@ -0,0 +1,6 @@ +{ + "sdk": { + "version": "6.0.100", + "rollForward": "latestMinor" + } +} \ No newline at end of file diff --git a/src/StrawberryShake/MetaPackages/Blazor/StrawberryShake.Blazor.csproj b/src/StrawberryShake/MetaPackages/Blazor/StrawberryShake.Blazor.csproj new file mode 100644 index 00000000000..ef6af4a30cb --- /dev/null +++ b/src/StrawberryShake/MetaPackages/Blazor/StrawberryShake.Blazor.csproj @@ -0,0 +1,30 @@ + + + + StrawberryShake.Blazor + StrawberryShake.Blazor + StrawberryShake + Abstractions and foundational APIs for StrawberryShake GraphQL clients. + false + $(NoWarn);NU5128 + false + + + + + + + + + + + + + + + + + + + + diff --git a/src/StrawberryShake/SourceGenerator/Directory.Build.props b/src/StrawberryShake/MetaPackages/Directory.Build.props similarity index 62% rename from src/StrawberryShake/SourceGenerator/Directory.Build.props rename to src/StrawberryShake/MetaPackages/Directory.Build.props index 58915223b7a..cf7f9fea726 100644 --- a/src/StrawberryShake/SourceGenerator/Directory.Build.props +++ b/src/StrawberryShake/MetaPackages/Directory.Build.props @@ -1,9 +1,10 @@ - - false + $(Library2TargetFrameworks) + $(NoWarn);CA1812 + diff --git a/src/StrawberryShake/SourceGenerator/.vscode/tasks.json b/src/StrawberryShake/SourceGenerator/.vscode/tasks.json deleted file mode 100644 index 31c32bd3457..00000000000 --- a/src/StrawberryShake/SourceGenerator/.vscode/tasks.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - // See https://go.microsoft.com/fwlink/?LinkId=733558 - // for the documentation about the tasks.json format - "version": "2.0.0", - "tasks": [ - { - "label": "build", - "command": "dotnet", - "type": "shell", - "args": [ - "build", - // Ask dotnet build to generate full paths for file names. - "/property:GenerateFullPaths=true", - // Do not generate summary otherwise it leads to duplicate errors in Problems panel - "/consoleloggerparameters:NoSummary" - ], - "group": "build", - "presentation": { - "reveal": "silent" - }, - "problemMatcher": "$msCompile" - } - ] -} \ No newline at end of file diff --git a/src/StrawberryShake/SourceGenerator/StrawberryShake.SourceGenerator.sln b/src/StrawberryShake/SourceGenerator/StrawberryShake.SourceGenerator.sln deleted file mode 100644 index f4830b32f16..00000000000 --- a/src/StrawberryShake/SourceGenerator/StrawberryShake.SourceGenerator.sln +++ /dev/null @@ -1,73 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.26124.0 -MinimumVisualStudioVersion = 15.0.26124.0 -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{CAECD940-C3AE-4589-AD83-B3F9EA9CB80A}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StrawberryShake.CodeGeneration.CSharp.Analyzers", "src\CodeGeneration.CSharp.Analyzers\StrawberryShake.CodeGeneration.CSharp.Analyzers.csproj", "{587B6DC4-BF55-4138-BB8A-F2F2503FDF00}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{8F0BFA5F-E5A0-4586-9ED4-6189286F4D3B}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StrawberryShake.CodeGeneration.CSharp.Analyzers.Tests", "test\CodeGeneration.CSharp.Analyzers.Tests\StrawberryShake.CodeGeneration.CSharp.Analyzers.Tests.csproj", "{C16A7FE1-E460-4B83-B093-012E9D27D5F2}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".referenced", ".referenced", "{9E66ECE3-81EF-4BCC-BE28-5AD884DB8572}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StrawberryShake.Tools.Configuration", "..\Tooling\src\Configuration\StrawberryShake.Tools.Configuration.csproj", "{B5BA7FA0-6BC2-48FC-8714-6C19A219C9A4}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - Release|Any CPU = Release|Any CPU - Release|x64 = Release|x64 - Release|x86 = Release|x86 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {587B6DC4-BF55-4138-BB8A-F2F2503FDF00}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {587B6DC4-BF55-4138-BB8A-F2F2503FDF00}.Debug|Any CPU.Build.0 = Debug|Any CPU - {587B6DC4-BF55-4138-BB8A-F2F2503FDF00}.Debug|x64.ActiveCfg = Debug|Any CPU - {587B6DC4-BF55-4138-BB8A-F2F2503FDF00}.Debug|x64.Build.0 = Debug|Any CPU - {587B6DC4-BF55-4138-BB8A-F2F2503FDF00}.Debug|x86.ActiveCfg = Debug|Any CPU - {587B6DC4-BF55-4138-BB8A-F2F2503FDF00}.Debug|x86.Build.0 = Debug|Any CPU - {587B6DC4-BF55-4138-BB8A-F2F2503FDF00}.Release|Any CPU.ActiveCfg = Release|Any CPU - {587B6DC4-BF55-4138-BB8A-F2F2503FDF00}.Release|Any CPU.Build.0 = Release|Any CPU - {587B6DC4-BF55-4138-BB8A-F2F2503FDF00}.Release|x64.ActiveCfg = Release|Any CPU - {587B6DC4-BF55-4138-BB8A-F2F2503FDF00}.Release|x64.Build.0 = Release|Any CPU - {587B6DC4-BF55-4138-BB8A-F2F2503FDF00}.Release|x86.ActiveCfg = Release|Any CPU - {587B6DC4-BF55-4138-BB8A-F2F2503FDF00}.Release|x86.Build.0 = Release|Any CPU - {C16A7FE1-E460-4B83-B093-012E9D27D5F2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C16A7FE1-E460-4B83-B093-012E9D27D5F2}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C16A7FE1-E460-4B83-B093-012E9D27D5F2}.Debug|x64.ActiveCfg = Debug|Any CPU - {C16A7FE1-E460-4B83-B093-012E9D27D5F2}.Debug|x64.Build.0 = Debug|Any CPU - {C16A7FE1-E460-4B83-B093-012E9D27D5F2}.Debug|x86.ActiveCfg = Debug|Any CPU - {C16A7FE1-E460-4B83-B093-012E9D27D5F2}.Debug|x86.Build.0 = Debug|Any CPU - {C16A7FE1-E460-4B83-B093-012E9D27D5F2}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C16A7FE1-E460-4B83-B093-012E9D27D5F2}.Release|Any CPU.Build.0 = Release|Any CPU - {C16A7FE1-E460-4B83-B093-012E9D27D5F2}.Release|x64.ActiveCfg = Release|Any CPU - {C16A7FE1-E460-4B83-B093-012E9D27D5F2}.Release|x64.Build.0 = Release|Any CPU - {C16A7FE1-E460-4B83-B093-012E9D27D5F2}.Release|x86.ActiveCfg = Release|Any CPU - {C16A7FE1-E460-4B83-B093-012E9D27D5F2}.Release|x86.Build.0 = Release|Any CPU - {B5BA7FA0-6BC2-48FC-8714-6C19A219C9A4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B5BA7FA0-6BC2-48FC-8714-6C19A219C9A4}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B5BA7FA0-6BC2-48FC-8714-6C19A219C9A4}.Debug|x64.ActiveCfg = Debug|Any CPU - {B5BA7FA0-6BC2-48FC-8714-6C19A219C9A4}.Debug|x64.Build.0 = Debug|Any CPU - {B5BA7FA0-6BC2-48FC-8714-6C19A219C9A4}.Debug|x86.ActiveCfg = Debug|Any CPU - {B5BA7FA0-6BC2-48FC-8714-6C19A219C9A4}.Debug|x86.Build.0 = Debug|Any CPU - {B5BA7FA0-6BC2-48FC-8714-6C19A219C9A4}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B5BA7FA0-6BC2-48FC-8714-6C19A219C9A4}.Release|Any CPU.Build.0 = Release|Any CPU - {B5BA7FA0-6BC2-48FC-8714-6C19A219C9A4}.Release|x64.ActiveCfg = Release|Any CPU - {B5BA7FA0-6BC2-48FC-8714-6C19A219C9A4}.Release|x64.Build.0 = Release|Any CPU - {B5BA7FA0-6BC2-48FC-8714-6C19A219C9A4}.Release|x86.ActiveCfg = Release|Any CPU - {B5BA7FA0-6BC2-48FC-8714-6C19A219C9A4}.Release|x86.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(NestedProjects) = preSolution - {587B6DC4-BF55-4138-BB8A-F2F2503FDF00} = {CAECD940-C3AE-4589-AD83-B3F9EA9CB80A} - {C16A7FE1-E460-4B83-B093-012E9D27D5F2} = {8F0BFA5F-E5A0-4586-9ED4-6189286F4D3B} - {B5BA7FA0-6BC2-48FC-8714-6C19A219C9A4} = {9E66ECE3-81EF-4BCC-BE28-5AD884DB8572} - EndGlobalSection -EndGlobal diff --git a/src/StrawberryShake/SourceGenerator/src/CodeGeneration.CSharp.Analyzers/CSharpGeneratorClient.cs b/src/StrawberryShake/SourceGenerator/src/CodeGeneration.CSharp.Analyzers/CSharpGeneratorClient.cs deleted file mode 100644 index 983c667801e..00000000000 --- a/src/StrawberryShake/SourceGenerator/src/CodeGeneration.CSharp.Analyzers/CSharpGeneratorClient.cs +++ /dev/null @@ -1,56 +0,0 @@ -using System.Diagnostics; - -namespace StrawberryShake.CodeGeneration.CSharp.Analyzers; - -internal sealed class CSharpGeneratorClient -{ - private readonly string _codeGenServer; - - public CSharpGeneratorClient(string codeGenServer) - { - _codeGenServer = codeGenServer; - } - - public GeneratorResponse Execute(GeneratorRequest request) - { - try - { - var fileSink = RequestFormatter.Format(request); - - var childProcess = Process.Start( - new ProcessStartInfo - { - FileName = "dotnet", - Arguments = $"\"{_codeGenServer}\" \"{fileSink}\"", - CreateNoWindow = true, - UseShellExecute = false - }); - - if (childProcess is null) - { - return CreateErrorResponse("Unable to generate client!"); - } - - childProcess.WaitForExit(); - - if (childProcess.ExitCode != 0) - { - return CreateErrorResponse("An error happened while generating the code."); - } - - return ResponseFormatter.Take(fileSink); - } - catch (Exception ex) - { - return CreateErrorResponse(ex); - } - } - - private static GeneratorResponse CreateErrorResponse(Exception exception) - => CreateErrorResponse(exception.Message + Environment.NewLine + exception.StackTrace); - - private static GeneratorResponse CreateErrorResponse(string message) - => new GeneratorResponse( - Array.Empty(), - new[] { new GeneratorError("SSG0005", "Generator Error", message) }); -} diff --git a/src/StrawberryShake/SourceGenerator/src/CodeGeneration.CSharp.Analyzers/DiagnosticErrorHelper.cs b/src/StrawberryShake/SourceGenerator/src/CodeGeneration.CSharp.Analyzers/DiagnosticErrorHelper.cs deleted file mode 100644 index 67cfb0cca83..00000000000 --- a/src/StrawberryShake/SourceGenerator/src/CodeGeneration.CSharp.Analyzers/DiagnosticErrorHelper.cs +++ /dev/null @@ -1,42 +0,0 @@ -using Microsoft.CodeAnalysis; -using static StrawberryShake.CodeGeneration.CSharp.Analyzers.Properties.AnalyzerResources; - -namespace StrawberryShake.CodeGeneration.CSharp.Analyzers; - -internal static class DiagnosticErrorHelper -{ - public const string ErrorCategory = "StrawberryShakeGenerator"; - - private const string _missingDependencyCode = "SS0004"; - - private const string _invalidClientNameCode = "SS0014"; - - private static readonly DiagnosticDescriptor _missingDependency = - new DiagnosticDescriptor( - id: _missingDependencyCode, - title: DiagnosticErrorHelper_ReportMissingDependency_Title, - messageFormat: DiagnosticErrorHelper_ReportMissingDependency_Message, - category: ErrorCategory, - DiagnosticSeverity.Error, - isEnabledByDefault: true); - - private static readonly DiagnosticDescriptor _invalidClientName = - new DiagnosticDescriptor( - id: _invalidClientNameCode, - title: DiagnosticErrorHelper_ReportMissingDependency_Title, - messageFormat: DiagnosticErrorHelper_ReportInvalidClientName_Message, - category: ErrorCategory, - DiagnosticSeverity.Error, - isEnabledByDefault: true); - - public static void ReportMissingDependency( - GeneratorExecutionContext context, - string packageName) => - context.ReportDiagnostic(_missingDependency, packageName); - - public static void ReportInvalidClientName( - GeneratorExecutionContext context, - string clientName, - string filePath) => - context.ReportDiagnostic(_invalidClientName, clientName, filePath, new Location(1, 1)); -} diff --git a/src/StrawberryShake/SourceGenerator/src/CodeGeneration.CSharp.Analyzers/GeneratorExecutionContextExtensions.cs b/src/StrawberryShake/SourceGenerator/src/CodeGeneration.CSharp.Analyzers/GeneratorExecutionContextExtensions.cs deleted file mode 100644 index 1d7b8efa754..00000000000 --- a/src/StrawberryShake/SourceGenerator/src/CodeGeneration.CSharp.Analyzers/GeneratorExecutionContextExtensions.cs +++ /dev/null @@ -1,80 +0,0 @@ -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.Text; - -namespace StrawberryShake.CodeGeneration.CSharp.Analyzers; - -internal static class GeneratorExecutionContextExtensions -{ - public static void ReportDiagnostic( - this GeneratorExecutionContext context, - DiagnosticDescriptor descriptor, - string filePath, - Location location, - params object[] messageArgs) => - context.ReportDiagnostic(Diagnostic.Create( - descriptor, - Microsoft.CodeAnalysis.Location.Create( - filePath, - TextSpan.FromBounds(1, 2), - new LinePositionSpan( - new LinePosition( - location.Line, - location.Column), - new LinePosition( - location.Line, - location.Column + 1))), - messageArgs)); - - public static void ReportDiagnostic( - this GeneratorExecutionContext context, - DiagnosticDescriptor descriptor, - params object[] messageArgs) => - context.ReportDiagnostic( - Diagnostic.Create( - descriptor, - Microsoft.CodeAnalysis.Location.None, - messageArgs)); - - public static void ReportDiagnostic( - this GeneratorExecutionContext context, - string id, - string title, - string message) => - context.ReportDiagnostic( - Diagnostic.Create( - new DiagnosticDescriptor( - id: id, - title: title, - messageFormat: message, - category: DiagnosticErrorHelper.ErrorCategory, - DiagnosticSeverity.Error, - isEnabledByDefault: true), - Microsoft.CodeAnalysis.Location.None)); - - public static void ReportDiagnostic( - this GeneratorExecutionContext context, - string id, - string title, - string message, - string filePath, - Location location) => - context.ReportDiagnostic( - Diagnostic.Create( - new DiagnosticDescriptor( - id: id, - title: title, - messageFormat: message, - category: DiagnosticErrorHelper.ErrorCategory, - DiagnosticSeverity.Error, - isEnabledByDefault: true), - Microsoft.CodeAnalysis.Location.Create( - filePath, - TextSpan.FromBounds(1, 2), - new LinePositionSpan( - new LinePosition( - location.Line, - location.Column), - new LinePosition( - location.Line, - location.Column + 1))))); -} diff --git a/src/StrawberryShake/SourceGenerator/src/CodeGeneration.CSharp.Analyzers/Properties/AnalyzerResources.Designer.cs b/src/StrawberryShake/SourceGenerator/src/CodeGeneration.CSharp.Analyzers/Properties/AnalyzerResources.Designer.cs deleted file mode 100644 index 6d47787ac8c..00000000000 --- a/src/StrawberryShake/SourceGenerator/src/CodeGeneration.CSharp.Analyzers/Properties/AnalyzerResources.Designer.cs +++ /dev/null @@ -1,72 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace StrawberryShake.CodeGeneration.CSharp.Analyzers.Properties { - using System; - - - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] - [System.Diagnostics.DebuggerNonUserCodeAttribute()] - [System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class AnalyzerResources { - - private static System.Resources.ResourceManager resourceMan; - - private static System.Globalization.CultureInfo resourceCulture; - - [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal AnalyzerResources() { - } - - [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] - internal static System.Resources.ResourceManager ResourceManager { - get { - if (object.Equals(null, resourceMan)) { - System.Resources.ResourceManager temp = new System.Resources.ResourceManager("StrawberryShake.CodeGeneration.CSharp.Analyzers.Properties.AnalyzerResources", typeof(AnalyzerResources).Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] - internal static System.Globalization.CultureInfo Culture { - get { - return resourceCulture; - } - set { - resourceCulture = value; - } - } - - internal static string DiagnosticErrorHelper_ReportMissingDependency_Title { - get { - return ResourceManager.GetString("DiagnosticErrorHelper_ReportMissingDependency_Title", resourceCulture); - } - } - - internal static string DiagnosticErrorHelper_ReportMissingDependency_Message { - get { - return ResourceManager.GetString("DiagnosticErrorHelper_ReportMissingDependency_Message", resourceCulture); - } - } - - internal static string DiagnosticErrorHelper_ReportInvalidClientName_Message { - get { - return ResourceManager.GetString("DiagnosticErrorHelper_ReportInvalidClientName_Message", resourceCulture); - } - } - - internal static string FileLogger_FileLogger_LogFileCannotBeEmpty { - get { - return ResourceManager.GetString("FileLogger_FileLogger_LogFileCannotBeEmpty", resourceCulture); - } - } - } -} diff --git a/src/StrawberryShake/SourceGenerator/src/CodeGeneration.CSharp.Analyzers/Properties/AnalyzerResources.resx b/src/StrawberryShake/SourceGenerator/src/CodeGeneration.CSharp.Analyzers/Properties/AnalyzerResources.resx deleted file mode 100644 index d9372fc0e2a..00000000000 --- a/src/StrawberryShake/SourceGenerator/src/CodeGeneration.CSharp.Analyzers/Properties/AnalyzerResources.resx +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - text/microsoft-resx - - - 1.3 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - Dependency Missing - - - The package reference `{0}` is missing. - `dotnet add package {0}` - - - The client name `{0}` is invalid. A valid client name must start with an ASCII letter or an underscore and can contain ASCII letters, digits and underscores. - - - '{0}' cannot be null or empty. - - diff --git a/src/StrawberryShake/SourceGenerator/src/CodeGeneration.CSharp.Analyzers/SourceDocumentExtensions.cs b/src/StrawberryShake/SourceGenerator/src/CodeGeneration.CSharp.Analyzers/SourceDocumentExtensions.cs deleted file mode 100644 index 79d1c2ec2c6..00000000000 --- a/src/StrawberryShake/SourceGenerator/src/CodeGeneration.CSharp.Analyzers/SourceDocumentExtensions.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace StrawberryShake.CodeGeneration.CSharp.Analyzers; - -internal static class SourceDocumentExtensions -{ - public static IEnumerable SelectCSharp( - this IEnumerable documents) => - documents.Where(t => t.Kind is GeneratorDocumentKind.CSharp); -} diff --git a/src/StrawberryShake/SourceGenerator/src/CodeGeneration.CSharp.Analyzers/StrawberryShake.CodeGeneration.CSharp.Analyzers.csproj b/src/StrawberryShake/SourceGenerator/src/CodeGeneration.CSharp.Analyzers/StrawberryShake.CodeGeneration.CSharp.Analyzers.csproj deleted file mode 100644 index 60e125dd725..00000000000 --- a/src/StrawberryShake/SourceGenerator/src/CodeGeneration.CSharp.Analyzers/StrawberryShake.CodeGeneration.CSharp.Analyzers.csproj +++ /dev/null @@ -1,50 +0,0 @@ - - - - StrawberryShake.CodeGeneration.CSharp.Analyzers - StrawberryShake.CodeGeneration.CSharp.Analyzers - StrawberryShake.CodeGeneration.CSharp.Analyzers - StrawberryShake CSharp source generator. - netstandard2.0 - false - false - enable - true - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - - - - - - - - - - - - - ResXFileCodeGenerator - AnalyzerResources.Designer.cs - - - - - - True - True - AnalyzerResources.resx - - - - diff --git a/src/StrawberryShake/SourceGenerator/src/CodeGeneration.CSharp.Analyzers/StrawberryShakeSourceGenerator.cs b/src/StrawberryShake/SourceGenerator/src/CodeGeneration.CSharp.Analyzers/StrawberryShakeSourceGenerator.cs deleted file mode 100644 index a26c7c05d8f..00000000000 --- a/src/StrawberryShake/SourceGenerator/src/CodeGeneration.CSharp.Analyzers/StrawberryShakeSourceGenerator.cs +++ /dev/null @@ -1,151 +0,0 @@ -using System.Diagnostics.CodeAnalysis; -using Microsoft.CodeAnalysis; -using static System.IO.Path; - -namespace StrawberryShake.CodeGeneration.CSharp.Analyzers; - -[Generator] -public sealed class StrawberryShakeSourceGenerator : ISourceGenerator -{ - public void Initialize(GeneratorInitializationContext context) - { - } - - public void Execute(GeneratorExecutionContext context) - { - try - { - var codeGenServer = GetCodeGenServerLocation(context); - var documentFileNames = GetDocumentFileNames(context); - - var client = new CSharpGeneratorClient(codeGenServer); - - foreach (var configFileName in GetConfigFiles(context)) - { - Execute(context, client, configFileName, documentFileNames); - } - } - catch (Exception ex) - { - context.ReportDiagnostic( - Diagnostic.Create( - new DiagnosticDescriptor( - "SSG0003", - "Generator Error", - ex.Message + "\r\n" + ex.StackTrace, - "Generator", - DiagnosticSeverity.Error, - true), - Microsoft.CodeAnalysis.Location.None)); - } - } - - private static void Execute( - GeneratorExecutionContext context, - CSharpGeneratorClient client, - string configFileName, - IReadOnlyList documentFileNames) - { - GeneratorRequest request = new( - configFileName, - documentFileNames, - GetDirectoryName(configFileName), - GetDefaultNamespace(context), - GetPersistedQueryDirectory(context)); - GeneratorResponse response = client.Execute(request); - - foreach (GeneratorDocument document in response.Documents.SelectCSharp()) - { - context.AddSource(document.Name + ".g.cs", document.SourceText); - } - - if (response.Errors.Count > 0) - { - foreach (GeneratorError error in response.Errors) - { - if (error.Location is null || error.FilePath is null) - { - context.ReportDiagnostic( - error.Code, - error.Title, - error.Message); - } - else - { - context.ReportDiagnostic( - error.Code, - error.Title, - error.Message, - error.FilePath, - new Location(error.Location.Line, error.Location.Column)); - } - } - } - } - - private static string[] GetDocumentFileNames( - GeneratorExecutionContext context) => - context.AdditionalFiles - .Select(t => t.Path) - .Where(t => GetExtension(t).Equals(".graphql", StringComparison.OrdinalIgnoreCase)) - .ToArray(); - - private static IReadOnlyList GetConfigFiles( - GeneratorExecutionContext context) => - context.AdditionalFiles - .Select(t => t.Path) - .Where(t => GetFileName(t).Equals(".graphqlrc.json", StringComparison.OrdinalIgnoreCase)) - .ToList(); - - private static string GetDefaultNamespace(GeneratorExecutionContext context) - { - if (TryGetBuildProperty(context, "StrawberryShake_DefaultNamespace", out var ns)) - { - return ns; - } - - if (TryGetBuildProperty(context, "MSBuildProjectFile", out var projectFile)) - { - return GetFileNameWithoutExtension(projectFile); - } - - if (!string.IsNullOrEmpty(context.Compilation.Assembly.Name)) - { - return context.Compilation.Assembly.Name; - } - - return "StrawberryShake.Generated"; - } - - private static string GetCodeGenServerLocation(GeneratorExecutionContext context) - { - if (TryGetBuildProperty(context, "StrawberryShake_CodeGenServer", out var loc)) - { - return loc; - } - - throw new Exception("Could not locate the code generation server."); - } - - private static string? GetPersistedQueryDirectory(GeneratorExecutionContext context) - => TryGetBuildProperty(context, "StrawberryShake_PersistedQueryDirectory", out var loc) - ? loc - : null; - - private static bool TryGetBuildProperty( - GeneratorExecutionContext context, - string key, - [NotNullWhen(true)] out string? value) - { - if (context.AnalyzerConfigOptions.GlobalOptions.TryGetValue( - $"build_property.{key}", - out value) && - !string.IsNullOrEmpty(value)) - { - return true; - } - - value = null; - return false; - } -} diff --git a/src/StrawberryShake/SourceGenerator/src/Directory.Build.props b/src/StrawberryShake/SourceGenerator/src/Directory.Build.props deleted file mode 100644 index 7b260248297..00000000000 --- a/src/StrawberryShake/SourceGenerator/src/Directory.Build.props +++ /dev/null @@ -1,11 +0,0 @@ - - - - - net6.0; netstandard2.0 - netstandard2.0 - $(NoWarn);CA1812 - false - - - diff --git a/src/StrawberryShake/SourceGenerator/src/MSBuild/StrawberryShake.nuspec b/src/StrawberryShake/SourceGenerator/src/MSBuild/StrawberryShake.nuspec deleted file mode 100644 index cfbe6d6fff7..00000000000 --- a/src/StrawberryShake/SourceGenerator/src/MSBuild/StrawberryShake.nuspec +++ /dev/null @@ -1,21 +0,0 @@ - - - - StrawberryShake - 11.1.0 - ChilliCream authors and contributors - ChilliCream authors and contributors - true - https://github.com/ChilliCream/hotchocolate/blob/master/LICENSE - https://hotchocolate.io/ - https://chillicream.com/resources/strawberryshake-signet.png - Package Description - Release notes: https://github.com/ChilliCream/hotchocolate/releases/ - Copyright © 2019 ChilliCream (Michael & Rafael Staib) - GraphQL ChilliCream - - - - - - diff --git a/src/StrawberryShake/SourceGenerator/src/MSBuild/StrawberryShake.props b/src/StrawberryShake/SourceGenerator/src/MSBuild/StrawberryShake.props deleted file mode 100644 index 81860e8382f..00000000000 --- a/src/StrawberryShake/SourceGenerator/src/MSBuild/StrawberryShake.props +++ /dev/null @@ -1,9 +0,0 @@ - - - - $(MSBuildThisFileDirectory)..\analyzers\dotnet\cs - $(MSBuildThisFileDirectory)gen\BerryCodeGen.dll - - - - diff --git a/src/StrawberryShake/SourceGenerator/src/MSBuild/StrawberryShake.targets b/src/StrawberryShake/SourceGenerator/src/MSBuild/StrawberryShake.targets deleted file mode 100644 index 0373e5708e3..00000000000 --- a/src/StrawberryShake/SourceGenerator/src/MSBuild/StrawberryShake.targets +++ /dev/null @@ -1,40 +0,0 @@ - - - - $(RootNamespace) - $(AssemblyName) - - - - - - - - - - - - - - - - - - - - - - - - - - - - GraphQLCompile; - $(CoreCompileDependsOn) - - - - - - diff --git a/src/StrawberryShake/SourceGenerator/test/CodeGeneration.CSharp.Analyzers.Tests/Custom.cs b/src/StrawberryShake/SourceGenerator/test/CodeGeneration.CSharp.Analyzers.Tests/Custom.cs deleted file mode 100644 index 8cff27e41f2..00000000000 --- a/src/StrawberryShake/SourceGenerator/test/CodeGeneration.CSharp.Analyzers.Tests/Custom.cs +++ /dev/null @@ -1,5 +0,0 @@ -namespace StrawberryShake.CodeGeneration.CSharp.Analyzers.Tests; - -public class Custom -{ -} diff --git a/src/StrawberryShake/SourceGenerator/test/CodeGeneration.CSharp.Analyzers.Tests/CustomScalar/.graphqlrc.json b/src/StrawberryShake/SourceGenerator/test/CodeGeneration.CSharp.Analyzers.Tests/CustomScalar/.graphqlrc.json deleted file mode 100644 index b022b150244..00000000000 --- a/src/StrawberryShake/SourceGenerator/test/CodeGeneration.CSharp.Analyzers.Tests/CustomScalar/.graphqlrc.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "schema": "Schema.graphql", - "documents": "**/*.graphql", - "extensions": { - "strawberryShake": { - "name": "CustomScalarClient", - "url": "http://localhost:5000", - "dependencyInjection": true, - "requestStrategy": "PersistedQuery", - "hashAlgorithm": "md5", - "outputDirectoryName": ".generated", - "useSingleFile": true, - "transportProfiles": [ - { - "name": "Default", - "default": "HTTP", - "streamTransport": "WebSocket" - }, - { - "name": "WebSocket", - "default": "HTTP", - "query": "WebSocket", - "subscription": "WebSocket" - } - ] - } - } -} diff --git a/src/StrawberryShake/SourceGenerator/test/CodeGeneration.CSharp.Analyzers.Tests/CustomScalar/ChatGetPeople.graphql b/src/StrawberryShake/SourceGenerator/test/CodeGeneration.CSharp.Analyzers.Tests/CustomScalar/ChatGetPeople.graphql deleted file mode 100644 index 008e7be6908..00000000000 --- a/src/StrawberryShake/SourceGenerator/test/CodeGeneration.CSharp.Analyzers.Tests/CustomScalar/ChatGetPeople.graphql +++ /dev/null @@ -1,3 +0,0 @@ -query GetCustomValue { - customScalar -} diff --git a/src/StrawberryShake/SourceGenerator/test/CodeGeneration.CSharp.Analyzers.Tests/CustomScalar/Schema.extensions.graphql b/src/StrawberryShake/SourceGenerator/test/CodeGeneration.CSharp.Analyzers.Tests/CustomScalar/Schema.extensions.graphql deleted file mode 100644 index d3017489183..00000000000 --- a/src/StrawberryShake/SourceGenerator/test/CodeGeneration.CSharp.Analyzers.Tests/CustomScalar/Schema.extensions.graphql +++ /dev/null @@ -1,4 +0,0 @@ -extend scalar CustomScalar - @runtimeType(name: "global::StrawberryShake.CodeGeneration.CSharp.Analyzers.Tests.Custom") - -extend schema @key(fields: "id") diff --git a/src/StrawberryShake/SourceGenerator/test/CodeGeneration.CSharp.Analyzers.Tests/CustomScalar/Schema.graphql b/src/StrawberryShake/SourceGenerator/test/CodeGeneration.CSharp.Analyzers.Tests/CustomScalar/Schema.graphql deleted file mode 100644 index 7aad9ea04cb..00000000000 --- a/src/StrawberryShake/SourceGenerator/test/CodeGeneration.CSharp.Analyzers.Tests/CustomScalar/Schema.graphql +++ /dev/null @@ -1,5 +0,0 @@ -type Query { - customScalar: CustomScalar -} - -scalar CustomScalar diff --git a/src/StrawberryShake/SourceGenerator/test/CodeGeneration.CSharp.Analyzers.Tests/CustomScalar/Test.cs b/src/StrawberryShake/SourceGenerator/test/CodeGeneration.CSharp.Analyzers.Tests/CustomScalar/Test.cs deleted file mode 100644 index e6cd10a9325..00000000000 --- a/src/StrawberryShake/SourceGenerator/test/CodeGeneration.CSharp.Analyzers.Tests/CustomScalar/Test.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.Extensions.DependencyInjection; - -namespace StrawberryShake.CodeGeneration.CSharp.Analyzers.CustomScalar; - -public static class DependencyInjection -{ - public static void Configure(IServiceCollection services) - { - services.AddCustomScalarClient(); - } -} diff --git a/src/StrawberryShake/SourceGenerator/test/CodeGeneration.CSharp.Analyzers.Tests/StarWars/.graphqlrc.json b/src/StrawberryShake/SourceGenerator/test/CodeGeneration.CSharp.Analyzers.Tests/StarWars/.graphqlrc.json deleted file mode 100644 index 6900ee96be0..00000000000 --- a/src/StrawberryShake/SourceGenerator/test/CodeGeneration.CSharp.Analyzers.Tests/StarWars/.graphqlrc.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "schema": "Schema.graphql", - "documents": "**/*.graphql", - "extensions": { - "strawberryShake": { - "name": "StarWarsClient", - "url": "http://localhost:5000", - "dependencyInjection": true, - "requestStrategy": "PersistedQuery", - "hashAlgorithm": "md5", - "outputDirectoryName": ".generated", - "useSingleFile": true, - "transportProfiles": [ - { - "name": "Default", - "default": "HTTP", - "streamTransport": "WebSocket" - }, - { - "name": "WebSocket", - "default": "HTTP", - "query": "WebSocket", - "subscription": "WebSocket" - } - ] - } - } -} diff --git a/src/StrawberryShake/SourceGenerator/test/CodeGeneration.CSharp.Analyzers.Tests/StarWars/ChatGetPeople.graphql b/src/StrawberryShake/SourceGenerator/test/CodeGeneration.CSharp.Analyzers.Tests/StarWars/ChatGetPeople.graphql deleted file mode 100644 index 9787ebb01a0..00000000000 --- a/src/StrawberryShake/SourceGenerator/test/CodeGeneration.CSharp.Analyzers.Tests/StarWars/ChatGetPeople.graphql +++ /dev/null @@ -1,10 +0,0 @@ -query GetPeople { - people(order_by: { name: ASC }) { - nodes { - name - email - isOnline - lastSeen - } - } -} diff --git a/src/StrawberryShake/SourceGenerator/test/CodeGeneration.CSharp.Analyzers.Tests/StarWars/Schema.extensions.graphql b/src/StrawberryShake/SourceGenerator/test/CodeGeneration.CSharp.Analyzers.Tests/StarWars/Schema.extensions.graphql deleted file mode 100644 index 2bdfa414821..00000000000 --- a/src/StrawberryShake/SourceGenerator/test/CodeGeneration.CSharp.Analyzers.Tests/StarWars/Schema.extensions.graphql +++ /dev/null @@ -1 +0,0 @@ -extend schema @key(fields: "id") diff --git a/src/StrawberryShake/SourceGenerator/test/CodeGeneration.CSharp.Analyzers.Tests/StarWars/Schema.graphql b/src/StrawberryShake/SourceGenerator/test/CodeGeneration.CSharp.Analyzers.Tests/StarWars/Schema.graphql deleted file mode 100644 index 5de3d9fc934..00000000000 --- a/src/StrawberryShake/SourceGenerator/test/CodeGeneration.CSharp.Analyzers.Tests/StarWars/Schema.graphql +++ /dev/null @@ -1,298 +0,0 @@ -schema { - query: Query - mutation: Mutation - subscription: Subscription -} - -type Query { - "Gets the currently logged in user." - me: Person! - "Gets access to all the people known to this service." - people(after: String before: String first: Int last: Int order_by: PersonSort where: PersonFilter): PersonConnection - personByEmail(email: String!): Person! - personById(id: ID!): Person! -} - -type Mutation { - createUser(input: CreateUserInput!): CreateUserPayload! - inviteFriend(input: InviteFriendInput!): InviteFriendPayload! - login(input: LoginInput!): LoginPayload! - sendMessage(input: SendMessageInput!): SendMessagePayload! - typing(input: TypingInput!): TypingPayload! -} - -type Subscription { - onMessageReceived: Message! - onOnline: Person! - onTyping: Person! -} - -"The multiplier path scalar represents a valid GraphQL multiplier path string." -scalar MultiplierPath - -type Person { - addFriendId(id: ID!): Person! - email: String! - friends(after: String before: String first: Int last: Int order_by: PersonSort where: PersonFilter): PersonConnection - id: ID! - imageUri: Url - isOnline: Boolean! - lastSeen: DateTime! - messages(after: String before: String first: Int last: Int order_by: MessageSort where: MessageFilter): MessageConnection - name: String! -} - -input PersonFilter { - AND: [PersonFilter!] - email: String - email_contains: String - email_ends_with: String - email_in: [String!] - email_not: String - email_not_contains: String - email_not_ends_with: String - email_not_in: [String!] - email_not_starts_with: String - email_starts_with: String - id: ID - id_gt: ID - id_gte: ID - id_in: [ID!] - id_lt: ID - id_lte: ID - id_not: ID - id_not_gt: ID - id_not_gte: ID - id_not_in: [ID!] - id_not_lt: ID - id_not_lte: ID - lastSeen: DateTime - lastSeen_gt: DateTime - lastSeen_gte: DateTime - lastSeen_in: [DateTime!] - lastSeen_lt: DateTime - lastSeen_lte: DateTime - lastSeen_not: DateTime - lastSeen_not_gt: DateTime - lastSeen_not_gte: DateTime - lastSeen_not_in: [DateTime!] - lastSeen_not_lt: DateTime - lastSeen_not_lte: DateTime - name: String - name_contains: String - name_ends_with: String - name_in: [String!] - name_not: String - name_not_contains: String - name_not_ends_with: String - name_not_in: [String!] - name_not_starts_with: String - name_starts_with: String - OR: [PersonFilter!] -} - -input PersonSort { - email: SortOperationKind - id: SortOperationKind - lastSeen: SortOperationKind - name: SortOperationKind -} - -scalar Int - -"A connection to a list of items." -type PersonConnection { - "A list of edges." - edges: [PersonEdge!] - "A flattened list of the nodes." - nodes: [Person] - "Information to aid in pagination." - pageInfo: PageInfo! - totalCount: Int! -} - -"A connection to a list of items." -type MessageConnection { - "A list of edges." - edges: [MessageEdge!] - "A flattened list of the nodes." - nodes: [Message] - "Information to aid in pagination." - pageInfo: PageInfo! - totalCount: Int! -} - -type Message { - direction: Direction! - id: ID! - recipient: Person! - sender: Person! - sent: DateTime! - text: String! -} - -input MessageFilter { - AND: [MessageFilter!] - id: ID - id_gt: ID - id_gte: ID - id_in: [ID!] - id_lt: ID - id_lte: ID - id_not: ID - id_not_gt: ID - id_not_gte: ID - id_not_in: [ID!] - id_not_lt: ID - id_not_lte: ID - OR: [MessageFilter!] - sent: DateTime - sent_gt: DateTime - sent_gte: DateTime - sent_in: [DateTime!] - sent_lt: DateTime - sent_lte: DateTime - sent_not: DateTime - sent_not_gt: DateTime - sent_not_gte: DateTime - sent_not_in: [DateTime!] - sent_not_lt: DateTime - sent_not_lte: DateTime - text: String - text_contains: String - text_ends_with: String - text_in: [String!] - text_not: String - text_not_contains: String - text_not_ends_with: String - text_not_in: [String!] - text_not_starts_with: String - text_starts_with: String -} - -input MessageSort { - id: SortOperationKind - sent: SortOperationKind - text: SortOperationKind -} - -enum SortOperationKind { - ASC - DESC -} - -"Information about pagination in a connection." -type PageInfo { - "When paginating forwards, the cursor to continue." - endCursor: String - "Indicates whether more edges exist following the set defined by the clients arguments." - hasNextPage: Boolean! - "Indicates whether more edges exist prior the set defined by the clients arguments." - hasPreviousPage: Boolean! - "When paginating backwards, the cursor to continue." - startCursor: String -} - -"An edge in a connection." -type PersonEdge { - "A cursor for use in pagination." - cursor: String! - "The item at the end of the edge." - node: Person -} - -"An edge in a connection." -type MessageEdge { - "A cursor for use in pagination." - cursor: String! - "The item at the end of the edge." - node: Message -} - -type InviteFriendPayload { - clientMutationId: String - me: Person! -} - -input InviteFriendInput { - clientMutationId: String - email: String! -} - -input TypingInput { - "The client mutation id which can be optionally provided with a mutation." - clientMutationId: String - "The email of the person to which a message is being typed." - writingTo: String! -} - -type TypingPayload { - "The client mutation id which can be optionally provided with a mutation." - clientMutationId: String - "The person to which a message is being typed." - recipient: Person! - "The email of the person who is typing the message." - sender: Person! -} - -type CreateUserPayload { - clientMutationId: String - user: User! -} - -input CreateUserInput { - clientMutationId: String - email: String! - image: Url - name: String! - password: String! -} - -input LoginInput { - clientMutationId: String - email: String! - password: String! -} - -type LoginPayload { - clientMutationId: String - me: Person! - scheme: String! - token: String! -} - -type SendMessagePayload { - clientMutationId: String - message: Message! - recipient: Person! - sender: Person! -} - -input SendMessageInput { - clientMutationId: String - "The email of the person to which a message shall be send." - recipientEmail: String! - "The message text." - text: String! -} - -enum Direction { - INCOMING - OUTGOING -} - -"The `DateTime` scalar represents an ISO-8601 compliant date time type." -scalar DateTime - -scalar Url - -type User { - email: String! - id: ID! - personId: ID! -} - -"The cost directives is used to express the complexity of a field." -directive @cost("Defines the complexity of the field." complexity: Int! = 1 "Defines field arguments that act as complexity multipliers." multipliers: [MultiplierPath!]) on FIELD_DEFINITION - -directive @authorize("The name of the authorization policy that determines access to the annotated resource." policy: String "Roles that are allowed to access to the annotated resource." roles: [String!]) repeatable on OBJECT | FIELD_DEFINITION \ No newline at end of file diff --git a/src/StrawberryShake/SourceGenerator/test/CodeGeneration.CSharp.Analyzers.Tests/StarWars/Test.cs b/src/StrawberryShake/SourceGenerator/test/CodeGeneration.CSharp.Analyzers.Tests/StarWars/Test.cs deleted file mode 100644 index 7b18de69bf8..00000000000 --- a/src/StrawberryShake/SourceGenerator/test/CodeGeneration.CSharp.Analyzers.Tests/StarWars/Test.cs +++ /dev/null @@ -1,46 +0,0 @@ -using Microsoft.Extensions.DependencyInjection; - -namespace StrawberryShake.CodeGeneration.CSharp.Analyzers.StarWars; - -public static class DependencyInjection -{ - public static void Configure(IServiceCollection services) - { - services.AddStarWarsClient(); - } -} - - -/* -public static class Utilities -{ - private static string? GetGeneratedOutput(string sourceCode) - { - var syntaxTree = CSharpSyntaxTree.ParseText(sourceCode); - var references = AppDomain.CurrentDomain.GetAssemblies() - .Where(assembly => !assembly.IsDynamic) - .Select(assembly => MetadataReference - .CreateFromFile(assembly.Location)) - .Cast(); - - var compilation = CSharpCompilation.Create("SourceGeneratorTests", - new[] { syntaxTree }, - references, - new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)); - - // Source Generator to test - var generator = new DemoSourceGenerator.DemoSourceGenerator(); - - CSharpGeneratorDriver.Create(generator) - .RunGeneratorsAndUpdateCompilation(compilation, - out var outputCompilation, - out var diagnostics); - - // optional - diagnostics.Where(d => d.Severity == DiagnosticSeverity.Error) - .Should().BeEmpty(); - - return outputCompilation.SyntaxTrees.Skip(1).LastOrDefault()?.ToString(); - } -} -*/ diff --git a/src/StrawberryShake/SourceGenerator/test/CodeGeneration.CSharp.Analyzers.Tests/StrawberryShake.CodeGeneration.CSharp.Analyzers.Tests.csproj b/src/StrawberryShake/SourceGenerator/test/CodeGeneration.CSharp.Analyzers.Tests/StrawberryShake.CodeGeneration.CSharp.Analyzers.Tests.csproj deleted file mode 100644 index 819a2dc087b..00000000000 --- a/src/StrawberryShake/SourceGenerator/test/CodeGeneration.CSharp.Analyzers.Tests/StrawberryShake.CodeGeneration.CSharp.Analyzers.Tests.csproj +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - true - $(BaseIntermediateOutputPath)\GeneratedFiles - $(BaseIntermediateOutputPath)\StrawberryShake.log - $(MSBuildThisFileDirectory)obj\GraphQL - $(MSBuildThisFileDirectory)..\..\src\.server\BerryCodeGen.dll - StrawberryShake.CodeGeneration.CSharp.Analyzers - - - - - - - - - - - - - - - - - - - - - - - - - Always - - - Always - - - - - - diff --git a/src/StrawberryShake/SourceGenerator/test/Directory.Build.props b/src/StrawberryShake/SourceGenerator/test/Directory.Build.props deleted file mode 100644 index 06c9a56d2f9..00000000000 --- a/src/StrawberryShake/SourceGenerator/test/Directory.Build.props +++ /dev/null @@ -1,27 +0,0 @@ - - - - - $(TestTargetFrameworks) - false - 0 - - - - - - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - - - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - - - - - - - diff --git a/src/StrawberryShake/Tooling/.vscode/launch.json b/src/StrawberryShake/Tooling/.vscode/launch.json index c67436b067d..b37497831c2 100644 --- a/src/StrawberryShake/Tooling/.vscode/launch.json +++ b/src/StrawberryShake/Tooling/.vscode/launch.json @@ -8,13 +8,10 @@ "type": "coreclr", "request": "launch", "preLaunchTask": "build", - "program": "${workspaceFolder}/src/dotnet-graphql/bin/Debug/netcoreapp3.1/dotnet-graphql.dll", + "program": "${workspaceFolder}/src/dotnet-graphql/bin/Debug/net7.0/dotnet-graphql.dll", "args": [ "generate", - "-p ${workspaceFolder}/src/dotnet-graphql/SchemaRegistry", - "-d", - "-l 8.0", - "-q file.json" + "/Users/michael/local/play/StrawberryBuildTests", ], "cwd": "${workspaceFolder}/src/dotnet-graphql", "console": "internalConsole", diff --git a/src/StrawberryShake/Tooling/src/Configuration/StrawberryShakeSettings.cs b/src/StrawberryShake/Tooling/src/Configuration/StrawberryShakeSettings.cs index d175e7bfd11..9f94d568b0a 100644 --- a/src/StrawberryShake/Tooling/src/Configuration/StrawberryShakeSettings.cs +++ b/src/StrawberryShake/Tooling/src/Configuration/StrawberryShakeSettings.cs @@ -25,22 +25,22 @@ public class StrawberryShakeSettings /// /// Defines if the generator shall generate dependency injection code. /// - public bool DependencyInjection { get; set; } = true; + public bool? DependencyInjection { get; set; } /// /// Defines if the generator shall validate the schema. /// - public bool StrictSchemaValidation { get; set; } = true; + public bool? StrictSchemaValidation { get; set; } /// /// Gets or sets the persisted query hash algorithm. /// - public string HashAlgorithm { get; set; } = "md5"; + public string? HashAlgorithm { get; set; } /// /// Defines that only a single code file shall be generated. /// - public bool UseSingleFile { get; set; } = true; + public bool? UseSingleFile { get; set; } /// /// Defines the default request strategy. @@ -56,12 +56,12 @@ public class StrawberryShakeSettings /// /// Defines if a client shall be generated without a store. /// - public bool NoStore { get; set; } = false; + public bool? NoStore { get; set; } /// /// Defines if the generator shall generate blazor query components. /// - public bool RazorComponents { get; set; } = false; + public bool? RazorComponents { get; set; } /// /// Gets the record generator settings. diff --git a/src/StrawberryShake/Tooling/src/dotnet-graphql/CommandTools.cs b/src/StrawberryShake/Tooling/src/dotnet-graphql/CommandTools.cs index c7f0338705a..ff356b5391f 100644 --- a/src/StrawberryShake/Tooling/src/dotnet-graphql/CommandTools.cs +++ b/src/StrawberryShake/Tooling/src/dotnet-graphql/CommandTools.cs @@ -15,7 +15,7 @@ public static void Write(this IEnumerable errors) { var message = new StringBuilder(); - foreach (HCError error in errors) + foreach (var error in errors) { Write(error, message); } @@ -37,7 +37,7 @@ public static void Write(this HCError error, StringBuilder message) if (error.Locations is { } && error.Locations.Count > 0) { - HotChocolate.Location location = error.Locations[0]; + var location = error.Locations[0]; message.Append($"({location.Line},{location.Column}): "); } message.Append($"error {error.Code ?? "GQL"}: {error.Message}"); diff --git a/src/StrawberryShake/Tooling/src/dotnet-graphql/CustomHeaderHelper.cs b/src/StrawberryShake/Tooling/src/dotnet-graphql/CustomHeaderHelper.cs index 175d46d31de..c2c28c92a36 100644 --- a/src/StrawberryShake/Tooling/src/dotnet-graphql/CustomHeaderHelper.cs +++ b/src/StrawberryShake/Tooling/src/dotnet-graphql/CustomHeaderHelper.cs @@ -5,7 +5,7 @@ namespace StrawberryShake.Tools public static class CustomHeaderHelper { public static Dictionary> ParseHeadersArgument( - List arguments) + IReadOnlyCollection arguments) { var headers = new Dictionary>(); diff --git a/src/StrawberryShake/Tooling/src/dotnet-graphql/DefaultConsoleOutputActivity.cs b/src/StrawberryShake/Tooling/src/dotnet-graphql/DefaultConsoleOutputActivity.cs index edb157e69ea..c28496a90f5 100644 --- a/src/StrawberryShake/Tooling/src/dotnet-graphql/DefaultConsoleOutputActivity.cs +++ b/src/StrawberryShake/Tooling/src/dotnet-graphql/DefaultConsoleOutputActivity.cs @@ -31,7 +31,7 @@ public void WriteError(HotChocolate.IError error) public void WriteErrors(IEnumerable errors) { - foreach (HotChocolate.IError error in errors) + foreach (var error in errors) { _hasErrors = true; error.Write(); diff --git a/src/StrawberryShake/Tooling/src/dotnet-graphql/DefaultFileSystem.cs b/src/StrawberryShake/Tooling/src/dotnet-graphql/DefaultFileSystem.cs index bdf03d44247..39161bb1bb1 100644 --- a/src/StrawberryShake/Tooling/src/dotnet-graphql/DefaultFileSystem.cs +++ b/src/StrawberryShake/Tooling/src/dotnet-graphql/DefaultFileSystem.cs @@ -25,12 +25,12 @@ public void EnsureDirectoryExists(string path) public IEnumerable GetClientDirectories(string path) { - foreach (string configFile in Directory.GetFiles( + foreach (var configFile in Directory.GetFiles( Environment.CurrentDirectory, WellKnownFiles.Config, SearchOption.AllDirectories)) { - string directory = Path.GetDirectoryName(configFile)!; + var directory = Path.GetDirectoryName(configFile)!; if (Directory.GetFiles(directory, _graphQLFilter).Length > 0) { yield return directory; @@ -76,7 +76,7 @@ public async Task WriteToAsync(string fileName, Func write) File.Delete(fileName); } - using (FileStream stream = File.Create(fileName)) + using (var stream = File.Create(fileName)) { await write(stream).ConfigureAwait(false); } diff --git a/src/StrawberryShake/Tooling/src/dotnet-graphql/DownloadCommand.cs b/src/StrawberryShake/Tooling/src/dotnet-graphql/DownloadCommand.cs index 0de742a07fd..29bae2a8c2c 100644 --- a/src/StrawberryShake/Tooling/src/dotnet-graphql/DownloadCommand.cs +++ b/src/StrawberryShake/Tooling/src/dotnet-graphql/DownloadCommand.cs @@ -9,28 +9,28 @@ public static void Build(CommandLineApplication download) { download.Description = "Download the schema as GraphQL SDL"; - CommandArgument uriArg = download.Argument( + var uriArg = download.Argument( "uri", "The URL to the GraphQL endpoint.", c => c.IsRequired()); - CommandOption fileNameArg = download.Option( + var fileNameArg = download.Option( "-f|--FileName", "The file name to store the schema SDL.", CommandOptionType.SingleValue); - CommandOption jsonArg = download.Option( + var jsonArg = download.Option( "-j|--json", "Console output as JSON.", CommandOptionType.NoValue); - CommandOption headersArg = download.Option( + var headersArg = download.Option( "-x|--headers", "Custom headers used in request to Graph QL server. " + "Can be used multiple times. Example: --headers key1=value1 --headers key2=value2", CommandOptionType.MultipleValue); - AuthArguments authArguments = download.AddAuthArguments(); + var authArguments = download.AddAuthArguments(); download.OnExecuteAsync(cancellationToken => { @@ -39,7 +39,7 @@ public static void Build(CommandLineApplication download) fileNameArg, authArguments, headersArg); - DownloadCommandHandler handler = + var handler = CommandTools.CreateHandler(jsonArg); return handler.ExecuteAsync(arguments, cancellationToken); }); diff --git a/src/StrawberryShake/Tooling/src/dotnet-graphql/DownloadCommandHandler.cs b/src/StrawberryShake/Tooling/src/dotnet-graphql/DownloadCommandHandler.cs index 8767d467f07..0f1ffcb0aad 100644 --- a/src/StrawberryShake/Tooling/src/dotnet-graphql/DownloadCommandHandler.cs +++ b/src/StrawberryShake/Tooling/src/dotnet-graphql/DownloadCommandHandler.cs @@ -29,9 +29,9 @@ public class DownloadCommandHandler DownloadCommandArguments arguments, CancellationToken cancellationToken) { - using IDisposable command = Output.WriteCommand(); + using var command = Output.WriteCommand(); - AccessToken? accessToken = + var accessToken = await arguments.AuthArguments .RequestTokenAsync(Output, cancellationToken) .ConfigureAwait(false); @@ -56,9 +56,9 @@ await arguments.AuthArguments DownloadCommandContext context, CancellationToken cancellationToken) { - using IActivity activity = Output.WriteActivity("Download schema"); + using var activity = Output.WriteActivity("Download schema"); - HttpClient client = HttpClientFactory.Create( + var client = HttpClientFactory.Create( context.Uri, context.Token, context.Scheme, context.CustomHeaders); return await IntrospectionHelper.DownloadSchemaAsync( diff --git a/src/StrawberryShake/Tooling/src/dotnet-graphql/ExportCommand.cs b/src/StrawberryShake/Tooling/src/dotnet-graphql/ExportCommand.cs index afda9092bc4..e24361e2ebd 100644 --- a/src/StrawberryShake/Tooling/src/dotnet-graphql/ExportCommand.cs +++ b/src/StrawberryShake/Tooling/src/dotnet-graphql/ExportCommand.cs @@ -1,6 +1,5 @@ using McMaster.Extensions.CommandLineUtils; using StrawberryShake.CodeGeneration.CSharp; -using StrawberryShake.CodeGeneration.CSharp.Analyzers; using StrawberryShake.Tools.Configuration; using static System.Environment; using static StrawberryShake.Tools.GeneratorHelpers; @@ -13,21 +12,21 @@ public static void Build(CommandLineApplication generate) { generate.Description = "Exports Persisted Queries for Strawberry Shake Clients"; - CommandArgument pathArg = generate.Argument( + var pathArg = generate.Argument( "path", "The project directory."); - CommandOption razorArg = generate.Option( + var razorArg = generate.Option( "-o|--outputPath", "Output Directory.", CommandOptionType.SingleValue); - CommandOption relayFormatArg = generate.Option( + var relayFormatArg = generate.Option( "-r|--relayFormat", "Export Persisted Queries as Relay Format.", CommandOptionType.NoValue); - CommandOption jsonArg = generate.Option( + var jsonArg = generate.Option( "-j|--json", "Console output as JSON.", CommandOptionType.NoValue); @@ -56,6 +55,7 @@ public ExportCommandHandler(IConsoleOutput output) ExportCommandArguments arguments, CancellationToken cancellationToken) { + /* using var activity = Output.WriteActivity("Export Persisted Queries"); if (string.IsNullOrEmpty(arguments.OutputPath)) @@ -91,6 +91,7 @@ public ExportCommandHandler(IConsoleOutput output) return 1; } } + */ return 0; } diff --git a/src/StrawberryShake/Tooling/src/dotnet-graphql/GenerateCommand.cs b/src/StrawberryShake/Tooling/src/dotnet-graphql/GenerateCommand.cs index d50ca835b4e..72e46dbdb46 100644 --- a/src/StrawberryShake/Tooling/src/dotnet-graphql/GenerateCommand.cs +++ b/src/StrawberryShake/Tooling/src/dotnet-graphql/GenerateCommand.cs @@ -1,6 +1,6 @@ using McMaster.Extensions.CommandLineUtils; using StrawberryShake.CodeGeneration.CSharp; -using StrawberryShake.CodeGeneration.CSharp.Analyzers; +using StrawberryShake.Tools.Configuration; using static System.Environment; using static StrawberryShake.Tools.GeneratorHelpers; @@ -12,16 +12,41 @@ public static void Build(CommandLineApplication generate) { generate.Description = "Generates Strawberry Shake Clients"; - CommandArgument pathArg = generate.Argument( + var pathArg = generate.Argument( "path", "The project directory."); - CommandOption razorArg = generate.Option( - "-r|--razor", - "Generate Razor Components", + var rootNamespaceArg = generate.Option( + "-n|--rootNamespace", + "The root namespace.", + CommandOptionType.SingleValue); + + var disableSchemaValidationArg = generate.Option( + "-s|--disableSchemaValidation", + "Disable strict schema validation.", + CommandOptionType.NoValue); + + var hashAlgorithmArg = generate.Option( + "-a|--hashAlgorithm", + "Request Hash Generation.", + CommandOptionType.SingleValue); + + var disableStoreArg = generate.Option( + "-t|--disableStore", + "Disable the client store.", + CommandOptionType.NoValue); + + var razorComponentsArg = generate.Option( + "-r|--razorComponents", + "Generate Razor components.", CommandOptionType.NoValue); - CommandOption jsonArg = generate.Option( + var outputDirArg = generate.Option( + "-o|--outputDirectory", + "The output directory.", + CommandOptionType.SingleValue); + + var jsonArg = generate.Option( "-j|--json", "Console output as JSON.", CommandOptionType.NoValue); @@ -30,7 +55,13 @@ public static void Build(CommandLineApplication generate) { var arguments = new GenerateCommandArguments( pathArg.Value ?? CurrentDirectory, - razorArg.HasValue()); + rootNamespaceArg.Value(), + !disableSchemaValidationArg.HasValue(), + hashAlgorithmArg.Value() ?? "md5", + true, + disableStoreArg.HasValue(), + razorComponentsArg.HasValue(), + outputDirArg.Value()); var handler = CommandTools.CreateHandler(jsonArg); return handler.ExecuteAsync(arguments, ct); }); @@ -43,51 +74,106 @@ public GenerateCommandHandler(IConsoleOutput output) Output = output; } - public IConsoleOutput Output { get; } + private IConsoleOutput Output { get; } - public override Task ExecuteAsync( - GenerateCommandArguments arguments, + public override async Task ExecuteAsync( + GenerateCommandArguments args, CancellationToken cancellationToken) { - using var activity = Output.WriteActivity( - arguments.RazorOnly - ? "Generate Razor Components" - : "Generate C# Clients"); - - var generator = new CSharpGeneratorClient(GetCodeGenServerLocation()); - var documents = GetDocuments(arguments.Path); + using var activity = Output.WriteActivity("Generate C# Clients"); + var statusCode = 0; - foreach (var configFileName in GetConfigFiles(arguments.Path)) + foreach (var configFileName in GetConfigFiles(args.Path)) { - var request = new GeneratorRequest( - configFileName, - documents, - option: arguments.RazorOnly - ? RequestOptions.GenerateRazorComponent - : RequestOptions.GenerateCSharpClient); - - var response = generator.Execute(request); - - if (response.TryLogErrors(activity)) + var configBody = await File.ReadAllTextAsync(configFileName, cancellationToken); + var config = GraphQLConfig.FromJson(configBody); + var clientName = config.Extensions.StrawberryShake.Name; + var rootNamespace = args.RootNamespace ?? $"{clientName}NS"; + var documents = GetGraphQLDocuments(args.Path, config.Documents); + var settings = CreateSettings(config, args, rootNamespace); + var result = CSharpGenerator.Generate(documents, settings); + var outputDir = args.OutputDir ?? Path.Combine( + Path.GetDirectoryName(configFileName)!, + config.Extensions.StrawberryShake.OutputDirectoryName); + + if (result.HasErrors()) { - return Task.FromResult(1); + statusCode = 1; + activity.WriteErrors(result.Errors); } + else + { + foreach (var doc in result.Documents) + { + if (doc.Kind is SourceDocumentKind.CSharp or SourceDocumentKind.Razor) + { + var fileName = doc.Path is null + ? Path.Combine(outputDir, doc.Name + ".cs") + : Path.Combine(outputDir, doc.Path, doc.Name + ".cs"); + var dir = Path.GetDirectoryName(fileName)!; + + if (!Directory.Exists(dir)) + { + Directory.CreateDirectory(dir); + } + + if (File.Exists(fileName)) + { + File.Delete(fileName); + } + + await File.WriteAllTextAsync( + fileName, + doc.SourceText, + cancellationToken); + + Output.WriteFileCreated(fileName); + } + } + } + } - return Task.FromResult(0); + return statusCode; } } - private sealed class GenerateCommandArguments + internal sealed class GenerateCommandArguments { - public GenerateCommandArguments(string path, bool razorOnly) + public GenerateCommandArguments( + string path, + string? rootNamespace, + bool strictSchemaValidation, + string hashAlgorithm, + bool useSingleFile, + bool noStore, + bool razorComponents, + string? outputDir) { Path = path; - RazorOnly = razorOnly; + RootNamespace = rootNamespace; + StrictSchemaValidation = strictSchemaValidation; + HashAlgorithm = hashAlgorithm; + UseSingleFile = useSingleFile; + NoStore = noStore; + RazorComponents = razorComponents; + OutputDir = outputDir; } public string Path { get; } - public bool RazorOnly { get; } + public string? RootNamespace { get; } + + public bool StrictSchemaValidation { get; } + + public string HashAlgorithm { get; } + + public bool UseSingleFile { get; } + + public bool NoStore { get; } + + public bool RazorComponents { get; } + + public string? OutputDir { get; } } } diff --git a/src/StrawberryShake/Tooling/src/dotnet-graphql/GeneratorHelpers.cs b/src/StrawberryShake/Tooling/src/dotnet-graphql/GeneratorHelpers.cs index 2c860953f7e..fe4ef5dc858 100644 --- a/src/StrawberryShake/Tooling/src/dotnet-graphql/GeneratorHelpers.cs +++ b/src/StrawberryShake/Tooling/src/dotnet-graphql/GeneratorHelpers.cs @@ -1,19 +1,99 @@ -using static System.IO.Directory; +using HotChocolate.Language; +using StrawberryShake.CodeGeneration; +using StrawberryShake.CodeGeneration.CSharp; +using StrawberryShake.Tools.Configuration; using static System.IO.Path; -using static System.IO.SearchOption; +using static GlobExpressions.Glob; namespace StrawberryShake.Tools; -public static class GeneratorHelpers +internal static class GeneratorHelpers { - public static string GetCodeGenServerLocation() - => Combine( - GetDirectoryName(typeof(GeneratorHelpers).Assembly.Location)!, - "..", "..", "..", "build", "gen", "BerryCodeGen.dll"); - public static string[] GetConfigFiles(string path) - => GetFiles(path, ".graphqlrc.json", AllDirectories); + { + const string pattern = "**/.graphqlrc.json"; + var binPath = Combine(path, "bin"); + var bin = Files(binPath, pattern).Select(t => Combine(binPath, t)).ToArray(); + var objPath = Combine(path, "obj"); + var obj = Files(objPath, pattern).Select(t => Combine(objPath, t)).ToArray(); + var files = Files(path, pattern).Select(t => Combine(path, t)).ToHashSet(); + + files.ExceptWith(bin); + files.ExceptWith(obj); + + return files.ToArray(); + } + + public static string[] GetGraphQLDocuments(string path, string pattern) + { + var binPath = Combine(path, "bin"); + var bin = Files(binPath, pattern).Select(t => Combine(binPath, t)).ToArray(); + var objPath = Combine(path, "obj"); + var obj = Files(objPath, pattern).Select(t => Combine(objPath, t)).ToArray(); + var files = Files(path, pattern).Select(t => Combine(path, t)).ToHashSet(); + + files.ExceptWith(bin); + files.ExceptWith(obj); + + return files.ToArray(); + } + + public static CSharpGeneratorSettings CreateSettings( + GraphQLConfig config, + GenerateCommand.GenerateCommandArguments args, + string rootNamespace) + { + var configSettings = config.Extensions.StrawberryShake; + return new CSharpGeneratorSettings + { + ClientName = configSettings.Name, + Namespace = configSettings.Namespace ?? args.RootNamespace ?? rootNamespace, + StrictSchemaValidation = + configSettings.StrictSchemaValidation ?? args.StrictSchemaValidation, + NoStore = configSettings.NoStore ?? args.NoStore, + InputRecords = configSettings.Records.Inputs, + EntityRecords = configSettings.Records.Entities, + RazorComponents = configSettings.RazorComponents ?? args.RazorComponents, + SingleCodeFile = configSettings.UseSingleFile ?? args.UseSingleFile, + RequestStrategy = configSettings.RequestStrategy, + HashProvider = GetHashProvider(configSettings.HashAlgorithm ?? args.HashAlgorithm), + TransportProfiles = MapTransportProfiles(configSettings.TransportProfiles) + }; + } + + private static IDocumentHashProvider GetHashProvider(string hashAlgorithm) + => hashAlgorithm.ToLowerInvariant() switch + { + "md5" => new MD5DocumentHashProvider(HashFormat.Hex), + "sha1" => new Sha1DocumentHashProvider(HashFormat.Hex), + "sha256" => new Sha256DocumentHashProvider(HashFormat.Hex), + _ => throw new NotSupportedException( + $"The hash algorithm `{hashAlgorithm}` is not supported.") + }; + + private static List MapTransportProfiles( + List transportProfileSettings) + { + var profiles = new List(); + + foreach (var settings in transportProfileSettings) + { + profiles.Add( + new TransportProfile( + settings.Name, + (TransportType)(int)settings.Default, + settings.Query.HasValue + ? (TransportType)(int)settings.Query + : null, + settings.Mutation.HasValue + ? (TransportType)(int)settings.Mutation + : null, + settings.Subscription.HasValue + ? (TransportType)(int)settings.Subscription + : null + )); + } - public static string[] GetDocuments(string path) - => GetFiles(path, "*.graphql", AllDirectories); + return profiles; + } } diff --git a/src/StrawberryShake/Tooling/src/dotnet-graphql/GeneratorResponseExtensions.cs b/src/StrawberryShake/Tooling/src/dotnet-graphql/GeneratorResponseExtensions.cs deleted file mode 100644 index 2e912103981..00000000000 --- a/src/StrawberryShake/Tooling/src/dotnet-graphql/GeneratorResponseExtensions.cs +++ /dev/null @@ -1,40 +0,0 @@ -using StrawberryShake.CodeGeneration.CSharp; - -namespace StrawberryShake.Tools; - -public static class GeneratorResponseExtensions -{ - public static bool TryLogErrors(this GeneratorResponse response, IActivity activity) - { - if (response.Errors.Count > 0) - { - foreach (GeneratorError error in response.Errors) - { - Dictionary? extensions = null; - if (error.FilePath is not null) - { - (extensions ??= new())["filePath"] = error.FilePath; - } - - List? locations = null; - if (error.Location is not null) - { - (locations ??= new()).Add( - new HotChocolate.Location( - error.Location.Line, - error.Location.Column)); - } - - activity.WriteError(new HotChocolate.Error( - error.Message, - error.Code, - locations: locations, - extensions: extensions)); - } - - return true; - } - - return false; - } -} diff --git a/src/StrawberryShake/Tooling/src/dotnet-graphql/InitCommand.cs b/src/StrawberryShake/Tooling/src/dotnet-graphql/InitCommand.cs index b7364a71f75..bf2ee78392a 100644 --- a/src/StrawberryShake/Tooling/src/dotnet-graphql/InitCommand.cs +++ b/src/StrawberryShake/Tooling/src/dotnet-graphql/InitCommand.cs @@ -9,33 +9,33 @@ public static void Build(CommandLineApplication init) { init.Description = "Initialize project and download schema"; - CommandArgument uriArg = init.Argument( + var uriArg = init.Argument( "uri", "The URL to the GraphQL endpoint.", c => c.IsRequired()); - CommandOption pathArg = init.Option( + var pathArg = init.Option( "-p|--Path", "The directory where the client shall be located.", CommandOptionType.SingleValue); - CommandOption nameArg = init.Option( + var nameArg = init.Option( "-n|--clientName", "The GraphQL client name.", CommandOptionType.SingleValue); - CommandOption jsonArg = init.Option( + var jsonArg = init.Option( "-j|--json", "Console output as JSON.", CommandOptionType.NoValue); - CommandOption headersArg = init.Option( + var headersArg = init.Option( "-x|--headers", "Custom headers used in request to Graph QL server. " + "Can be used mulitple times. Example: --headers key1=value1 --headers key2=value2", CommandOptionType.MultipleValue); - AuthArguments authArguments = init.AddAuthArguments(); + var authArguments = init.AddAuthArguments(); init.OnExecuteAsync(cancellationToken => { @@ -45,8 +45,7 @@ public static void Build(CommandLineApplication init) nameArg, authArguments, headersArg); - InitCommandHandler handler = - CommandTools.CreateHandler(jsonArg); + var handler = CommandTools.CreateHandler(jsonArg); return handler.ExecuteAsync(arguments, cancellationToken); }); } diff --git a/src/StrawberryShake/Tooling/src/dotnet-graphql/InitCommandHandler.cs b/src/StrawberryShake/Tooling/src/dotnet-graphql/InitCommandHandler.cs index 0270ff43030..d0e29b36657 100644 --- a/src/StrawberryShake/Tooling/src/dotnet-graphql/InitCommandHandler.cs +++ b/src/StrawberryShake/Tooling/src/dotnet-graphql/InitCommandHandler.cs @@ -32,9 +32,9 @@ public class InitCommandHandler InitCommandArguments arguments, CancellationToken cancellationToken) { - using IDisposable command = Output.WriteCommand(); + using var command = Output.WriteCommand(); - AccessToken? accessToken = + var accessToken = await arguments.AuthArguments .RequestTokenAsync(Output, cancellationToken) .ConfigureAwait(false); @@ -79,14 +79,14 @@ await arguments.AuthArguments return true; } - using IActivity activity = Output.WriteActivity("Download schema"); + using var activity = Output.WriteActivity("Download schema"); - string schemaFilePath = FileSystem.CombinePath( + var schemaFilePath = FileSystem.CombinePath( context.Path, context.SchemaFileName); - string schemaExtensionFilePath = FileSystem.CombinePath( + var schemaExtensionFilePath = FileSystem.CombinePath( context.Path, context.SchemaExtensionFileName); - HttpClient client = HttpClientFactory.Create( + var client = HttpClientFactory.Create( context.Uri, context.Token, context.Scheme, context.CustomHeaders); if (await IntrospectionHelper.DownloadSchemaAsync( @@ -108,9 +108,9 @@ await arguments.AuthArguments InitCommandContext context, CancellationToken cancellationToken) { - using IActivity activity = Output.WriteActivity("Client configuration"); + using var activity = Output.WriteActivity("Client configuration"); - string configFilePath = FileSystem.CombinePath( + var configFilePath = FileSystem.CombinePath( context.Path, context.ConfigFileName); var configuration = new GraphQLConfig diff --git a/src/StrawberryShake/Tooling/src/dotnet-graphql/JsonConsoleOutputActivity.cs b/src/StrawberryShake/Tooling/src/dotnet-graphql/JsonConsoleOutputActivity.cs index 18e324796b6..23712aa261c 100644 --- a/src/StrawberryShake/Tooling/src/dotnet-graphql/JsonConsoleOutputActivity.cs +++ b/src/StrawberryShake/Tooling/src/dotnet-graphql/JsonConsoleOutputActivity.cs @@ -36,7 +36,7 @@ public void WriteError(HotChocolate.IError error) public void WriteErrors(IEnumerable errors) { - foreach (HotChocolate.IError error in errors) + foreach (var error in errors) { _hasErrors = true; _data.Errors.Add(new JsonConsoleOutputErrorData(error)); diff --git a/src/StrawberryShake/Tooling/src/dotnet-graphql/OAuth/AuthArgumentsBase.cs b/src/StrawberryShake/Tooling/src/dotnet-graphql/OAuth/AuthArgumentsBase.cs index f440539cb8d..d29d05ac7e1 100644 --- a/src/StrawberryShake/Tooling/src/dotnet-graphql/OAuth/AuthArgumentsBase.cs +++ b/src/StrawberryShake/Tooling/src/dotnet-graphql/OAuth/AuthArgumentsBase.cs @@ -57,12 +57,12 @@ public sealed class AuthArguments if (TokenEndpoint.HasValue() || ClientId.HasValue() || ClientSecret.HasValue()) { - using IActivity activity = output.WriteActivity("Request token"); + using var activity = output.WriteActivity("Request token"); ValidateOAuthArguments(activity); - IEnumerable scopes = Scopes.HasValue() + var scopes = Scopes.HasValue() ? Scopes.Values.Where(t => t is { }).OfType() : Enumerable.Empty(); - string token = await TokenClient.GetTokenAsync( + var token = await TokenClient.GetTokenAsync( TokenEndpoint.Value()!.Trim(), ClientId.Value()!.Trim(), ClientSecret.Value()!.Trim(), diff --git a/src/StrawberryShake/Tooling/src/dotnet-graphql/OAuth/CommandLineApplicationExtensions.cs b/src/StrawberryShake/Tooling/src/dotnet-graphql/OAuth/CommandLineApplicationExtensions.cs index 5cf1f2b1599..fc0b927d325 100644 --- a/src/StrawberryShake/Tooling/src/dotnet-graphql/OAuth/CommandLineApplicationExtensions.cs +++ b/src/StrawberryShake/Tooling/src/dotnet-graphql/OAuth/CommandLineApplicationExtensions.cs @@ -7,38 +7,38 @@ public static class CommandLineApplicationExtensions public static AuthArguments AddAuthArguments( this CommandLineApplication app) { - CommandOption tokenEndpoint = app.Option( + var tokenEndpoint = app.Option( "--tokenEndpoint", "The token endpoint uri.", CommandOptionType.SingleValue); - CommandOption clientId = app.Option( + var clientId = app.Option( "--clientId", "The client id.", CommandOptionType.SingleValue, c => c.ShortName = null); - CommandOption clientSecret = app.Option( + var clientSecret = app.Option( "--clientSecret", "The client secret.", CommandOptionType.SingleValue); - CommandOption scopes = app.Option( + var scopes = app.Option( "--scope", "A custom scope that shall be passed along with the token request.", CommandOptionType.MultipleValue); - CommandOption token = app.Option( + var token = app.Option( "--token", "The token that shall be used to authenticate with the GraphQL server.", CommandOptionType.SingleValue); - CommandOption scheme = app.Option( + var scheme = app.Option( "--scheme", "The token scheme (default: bearer).", CommandOptionType.SingleValue); - CommandOption noScheme = app.Option( + var noScheme = app.Option( "--no-scheme", "The token will be send without a scheme.", CommandOptionType.NoValue); diff --git a/src/StrawberryShake/Tooling/src/dotnet-graphql/OAuth/TokenClient.cs b/src/StrawberryShake/Tooling/src/dotnet-graphql/OAuth/TokenClient.cs index c530cfa9c92..f337a1dc71c 100644 --- a/src/StrawberryShake/Tooling/src/dotnet-graphql/OAuth/TokenClient.cs +++ b/src/StrawberryShake/Tooling/src/dotnet-graphql/OAuth/TokenClient.cs @@ -15,8 +15,8 @@ public static class TokenClient IEnumerable scopes, CancellationToken cancellationToken = default) { - HttpClient client = new HttpClient(); - TokenResponse tokenRes = await client.RequestClientCredentialsTokenAsync( + var client = new HttpClient(); + var tokenRes = await client.RequestClientCredentialsTokenAsync( new ClientCredentialsTokenRequest { Address = tokenEndpoint, diff --git a/src/StrawberryShake/Tooling/src/dotnet-graphql/UpdateCommand.cs b/src/StrawberryShake/Tooling/src/dotnet-graphql/UpdateCommand.cs index c0e23ad0ecc..a976b047f83 100644 --- a/src/StrawberryShake/Tooling/src/dotnet-graphql/UpdateCommand.cs +++ b/src/StrawberryShake/Tooling/src/dotnet-graphql/UpdateCommand.cs @@ -9,28 +9,28 @@ public static void Build(CommandLineApplication update) { update.Description = "Update local schema"; - CommandOption pathArg = update.Option( + var pathArg = update.Option( "-p|--Path", "The directory where the client shall be located.", CommandOptionType.SingleValue); - CommandOption urlArg = update.Option( + var urlArg = update.Option( "-u|--uri", "The URL to the GraphQL endpoint.", CommandOptionType.SingleValue); - CommandOption jsonArg = update.Option( + var jsonArg = update.Option( "-j|--json", "Console output as JSON.", CommandOptionType.NoValue); - CommandOption headersArg = update.Option( + var headersArg = update.Option( "-x|--headers", "Custom headers used in request to Graph QL server. " + "Can be used mulitple times. Example: --headers key1=value1 --headers key2=value2", CommandOptionType.MultipleValue); - AuthArguments authArguments = update.AddAuthArguments(); + var authArguments = update.AddAuthArguments(); update.OnExecuteAsync(cancellationToken => { @@ -39,7 +39,7 @@ public static void Build(CommandLineApplication update) pathArg, authArguments, headersArg); - UpdateCommandHandler handler = CommandTools.CreateHandler(jsonArg); + var handler = CommandTools.CreateHandler(jsonArg); return handler.ExecuteAsync(arguments, cancellationToken); }); } diff --git a/src/StrawberryShake/Tooling/src/dotnet-graphql/UpdateCommandHandler.cs b/src/StrawberryShake/Tooling/src/dotnet-graphql/UpdateCommandHandler.cs index 959be2d91b4..c6d757a7b85 100644 --- a/src/StrawberryShake/Tooling/src/dotnet-graphql/UpdateCommandHandler.cs +++ b/src/StrawberryShake/Tooling/src/dotnet-graphql/UpdateCommandHandler.cs @@ -32,9 +32,9 @@ public class UpdateCommandHandler UpdateCommandArguments arguments, CancellationToken cancellationToken) { - using IDisposable command = Output.WriteCommand(); + using var command = Output.WriteCommand(); - AccessToken? accessToken = + var accessToken = await arguments.AuthArguments .RequestTokenAsync(Output, cancellationToken) .ConfigureAwait(false); @@ -57,7 +57,7 @@ await arguments.AuthArguments UpdateCommandContext context, CancellationToken cancellationToken) { - foreach (string path in FileSystem.GetClientDirectories(FileSystem.CurrentDirectory)) + foreach (var path in FileSystem.GetClientDirectories(FileSystem.CurrentDirectory)) { try { @@ -80,10 +80,10 @@ await arguments.AuthArguments string clientDirectory, CancellationToken cancellationToken) { - string configFilePath = Path.Combine(clientDirectory, WellKnownFiles.Config); + var configFilePath = Path.Combine(clientDirectory, WellKnownFiles.Config); var buffer = await FileSystem.ReadAllBytesAsync(configFilePath).ConfigureAwait(false); var json = Encoding.UTF8.GetString(buffer); - GraphQLConfig configuration = GraphQLConfig.FromJson(json); + var configuration = GraphQLConfig.FromJson(json); if (configuration is not null && await UpdateSchemaAsync(context, clientDirectory, configuration, cancellationToken) @@ -124,9 +124,9 @@ await UpdateSchemaAsync(context, clientDirectory, configuration, cancellationTok string schemaFilePath, CancellationToken cancellationToken) { - using IActivity activity = Output.WriteActivity("Download schema"); + using var activity = Output.WriteActivity("Download schema"); - HttpClient client = HttpClientFactory.Create( + var client = HttpClientFactory.Create( context.Uri ?? serviceUri, context.Token, context.Scheme, diff --git a/src/StrawberryShake/Tooling/src/dotnet-graphql/dotnet-graphql.csproj b/src/StrawberryShake/Tooling/src/dotnet-graphql/dotnet-graphql.csproj index 4c3dd1dec17..104074814f9 100644 --- a/src/StrawberryShake/Tooling/src/dotnet-graphql/dotnet-graphql.csproj +++ b/src/StrawberryShake/Tooling/src/dotnet-graphql/dotnet-graphql.csproj @@ -17,20 +17,16 @@ - + + + - - - - - - diff --git a/templates/Server/content/HotChocolate.Server.Template.csproj b/templates/Server/content/HotChocolate.Server.Template.csproj index 914389c5f6e..ad6a169e72f 100644 --- a/templates/Server/content/HotChocolate.Server.Template.csproj +++ b/templates/Server/content/HotChocolate.Server.Template.csproj @@ -6,9 +6,9 @@ - - - + + + diff --git a/templates/StarWars/content/StarWars.csproj b/templates/StarWars/content/StarWars.csproj index e14867f5eb6..0743f382307 100644 --- a/templates/StarWars/content/StarWars.csproj +++ b/templates/StarWars/content/StarWars.csproj @@ -1,4 +1,4 @@ - + net6.0 @@ -12,9 +12,9 @@ - - - + + + diff --git a/templates/v12/function/HotChocolate.Template.AzureFunctions.csproj b/templates/v12/function/HotChocolate.Template.AzureFunctions.csproj index 74502fcd5a9..fcc489077c8 100644 --- a/templates/v12/function/HotChocolate.Template.AzureFunctions.csproj +++ b/templates/v12/function/HotChocolate.Template.AzureFunctions.csproj @@ -16,8 +16,8 @@ - - + + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/templates/v12/server/HotChocolate.Template.Server.csproj b/templates/v12/server/HotChocolate.Template.Server.csproj index 34d7e0cbde8..a9c96ca7993 100644 --- a/templates/v12/server/HotChocolate.Template.Server.csproj +++ b/templates/v12/server/HotChocolate.Template.Server.csproj @@ -11,8 +11,8 @@ - - + + runtime; build; native; contentfiles; analyzers; buildtransitive all