diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json
index b718ad6a9..675ff81d8 100644
--- a/.config/dotnet-tools.json
+++ b/.config/dotnet-tools.json
@@ -3,7 +3,7 @@
"isRoot": true,
"tools": {
"gitversion.tool": {
- "version": "5.1.2",
+ "version": "5.8.1",
"commands": [
"dotnet-gitversion"
]
diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml
new file mode 100644
index 000000000..1becf7726
--- /dev/null
+++ b/.github/workflows/dotnet.yml
@@ -0,0 +1,69 @@
+name: Build and package
+
+on:
+ push:
+ branches:
+ - master
+ - release/**
+ tags:
+ - v**
+ pull_request:
+ branches: [master]
+
+env:
+ DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 1
+ DOTNET_CLI_TELEMETRY_OPTOUT: 1
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v2
+ with:
+ fetch-depth: 0
+
+ - name: Setup .NET
+ uses: actions/setup-dotnet@v1
+ with:
+ dotnet-version: 6.0.x
+
+ - name: Build packages
+ shell: pwsh
+ run: |
+ ./build.ps1 -Output ./artifacts -CurrentBranch $Env:GITHUB_REF_NAME
+
+ - name: Publish build artifacts
+ uses: actions/upload-artifact@v2
+ with:
+ name: Packages
+ path: |
+ ./artifacts/*.nupkg
+ ./artifacts/*.tgz
+
+ - name: Publish to nuget
+ if: github.ref_name == 'master' || startsWith(github.ref, 'refs/tags/')
+ shell: pwsh
+ env:
+ NUGET_KEY: ${{ secrets.NUGET_KEY }}
+ run: |
+ dotnet nuget push "./artifacts/*.nupkg" -k $Env:NUGET_KEY
+
+ - uses: actions/setup-node@v2
+ with:
+ node-version: "16.x"
+ registry-url: "https://registry.npmjs.org"
+
+ - name: Publish beta NPM package
+ if: github.ref_name == 'master'
+ env:
+ NODE_AUTH_TOKEN: ${{ secrets.NPM_KEY }}
+ working-directory: ./artifacts/graphql.server.link
+ run: npm publish --tag beta
+
+ - name: Publish release NPM package
+ if: startsWith(github.ref, 'refs/tags/')
+ env:
+ NODE_AUTH_TOKEN: ${{ secrets.NPM_KEY }}
+ working-directory: ./artifacts/graphql.server.link
+ run: npm publish
diff --git a/Directory.Build.props b/Directory.Build.props
index 58a660476..263d40170 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -1,7 +1,8 @@
+
- 9.0
+ 10.0
Pekka Heikura
https://github.com/pekkah/tanka-graphql
https://github.com/pekkah/tanka-graphql
@@ -10,4 +11,4 @@
graphql,tanka,signalr,apollo
Pekka Heikura
-
+
\ No newline at end of file
diff --git a/GitVersion.yml b/GitVersion.yml
index f0ed2fb64..e2162493b 100644
--- a/GitVersion.yml
+++ b/GitVersion.yml
@@ -1,4 +1,5 @@
mode: ContinuousDeployment
+next-version: 3.0
branches:
master:
tag: beta
diff --git a/artifacts/tanka-docs-section.yml b/artifacts/tanka-docs-section.yml
deleted file mode 100644
index 9a0472caf..000000000
--- a/artifacts/tanka-docs-section.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-id: artifacts
-type: artifacts
-includes:
- - "**/*.md"
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
deleted file mode 100644
index d3dbb9458..000000000
--- a/azure-pipelines.yml
+++ /dev/null
@@ -1,165 +0,0 @@
-name: 'graphql'
-
-variables:
- buildConfiguration: 'Release'
- DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 1
- DOTNET_CLI_TELEMETRY_OPTOUT: 1
-
-stages:
-- stage: Build
- jobs:
- - job: Build
- pool:
- vmImage: 'windows-latest'
- steps:
- - task: UseDotNet@2
- displayName: Use dotnet core SDK
- inputs:
- packageType: 'sdk'
- version: '3.1.x'
-
- - task: UseDotNet@2
- displayName: Use dotnet core SDK
- inputs:
- packageType: 'sdk'
- version: '5.0.x'
-
- - task: NodeTool@0
- displayName: "Install Node"
- inputs:
- versionSpec: "12.x"
- checkLatest: true
-
- - task: PowerShell@2
- displayName: build.ps1
- inputs:
- filePath: ./build.ps1
- arguments: -Output $(Build.StagingDirectory)/build
- errorActionPreference: 'continue'
- failOnStderr: false
- pwsh: true
-
- - task: PowerShell@2
- displayName: run-benchmarks.ps1
- inputs:
- filePath: ./run-benchmarks.ps1
- errorActionPreference: 'continue'
- failOnStderr: false
- pwsh: true
-
- - task: PowerShell@2
- displayName: build-docs.ps1
- inputs:
- filePath: ./build-docs.ps1
- arguments: -Output $(Build.StagingDirectory)/gh-pages
- errorActionPreference: 'continue'
- failOnStderr: false
- pwsh: true
-
- - task: PublishTestResults@2
- inputs:
- testResultsFormat: VSTest
- searchFolder: '$(Build.StagingDirectory)/build'
- testResultsFiles: '**/*.trx'
- mergeTestResults: false
-
- - publish: $(Build.StagingDirectory)
- artifact: artifacts
-
-- stage: Publish
- condition: or(eq(variables['Build.SourceBranch'], 'refs/heads/master'), startsWith(variables['Build.SourceBranch'], 'refs/tags'))
- jobs:
- - deployment: Deploy
- displayName: Publish packages
- pool:
- vmImage: ubuntu-latest
- environment: 'NuGets'
- strategy:
- runOnce:
- deploy:
- steps:
- - checkout: none
- - download: current
- artifact: artifacts
-
- - task: NuGetToolInstaller@1
- displayName: 'Use NuGet '
-
- - task: NuGetCommand@2
- displayName: 'NuGet push'
- inputs:
- command: push
- packagesToPush: '$(Pipeline.Workspace)/artifacts/build/**/*.nupkg'
- nuGetFeedType: external
- publishFeedCredentials: 'NuGet-TankaGraphQL'
- allowPackageConflicts: true
-
- - task: ExtractFiles@1
- displayName: 'Extract files '
- inputs:
- archiveFilePatterns: '$(Pipeline.Workspace)/artifacts/build/*.tgz'
- destinationFolder: '$(Pipeline.Workspace)/packages/'
- continueOnError: true
-
- - task: Npm@1
- enabled: true
- displayName: publish beta
- condition: eq(variables['Build.SourceBranch'], 'refs/heads/master')
- inputs:
- command: 'custom'
- workingDir: '$(Pipeline.Workspace)/packages/package'
- customCommand: 'publish --tag beta'
- customEndpoint: 'NPM'
-
- - task: Npm@1
- enabled: true
- displayName: 'npm publish latest'
- condition: startsWith(variables['Build.SourceBranch'], 'refs/tags')
- inputs:
- command: 'custom'
- workingDir: '$(Pipeline.Workspace)/packages/package'
- customCommand: 'publish'
- customEndpoint: 'NPM'
-
- - deployment: ghpages
- displayName: Publish gh-pages
- pool:
- vmImage: ubuntu-latest
- environment: 'NuGets'
- strategy:
- runOnce:
- deploy:
- steps:
- - download: current
- artifact: artifacts
- - checkout: self
- persistCredentials: true
- clean: true
- - script: |
- git config user.email "$(git.email)"
- git config user.name "$(git.name)"
- git checkout --track origin/gh-pages
- displayName: Use gh-pages
- - script: |
- cp -rv $(Pipeline.Workspace)/artifacts/gh-pages/** $(Build.SourcesDirectory)/
- displayName: Update files
- - script: |
- cd $(Build.SourcesDirectory)
- git add --all
- git status
- displayName: Add changes
- - script: |
- cd $(Build.SourcesDirectory)
- echo "BuildNumber: $(Build.BuildNumber)"
- git commit -m "$(Build.BuildNumber)"
- git status
- displayName: Commit
- - script: |
- cd $(Build.SourcesDirectory)
- git push
- git status
- enabled: true
- displayName: Push
-
-
-
diff --git a/benchmarks/graphql.benchmarks/ExecutionBenchmarks.cs b/benchmarks/graphql.benchmarks/ExecutionBenchmarks.cs
index 4da093b7d..fb7069d82 100644
--- a/benchmarks/graphql.benchmarks/ExecutionBenchmarks.cs
+++ b/benchmarks/graphql.benchmarks/ExecutionBenchmarks.cs
@@ -8,151 +8,150 @@
using Tanka.GraphQL.Language.Nodes;
using Tanka.GraphQL.TypeSystem;
-namespace Tanka.GraphQL.Benchmarks
+namespace Tanka.GraphQL.Benchmarks;
+
+[Orderer(SummaryOrderPolicy.FastestToSlowest)]
+[MemoryDiagnoser]
+[MarkdownExporterAttribute.GitHub]
+public class ExecutionBenchmarks
{
- [Orderer(SummaryOrderPolicy.FastestToSlowest)]
- [MemoryDiagnoser]
- [MarkdownExporterAttribute.GitHub]
- public class ExecutionBenchmarks
- {
- private ExecutableDocument _mutation;
- private ExecutableDocument _query;
- private ISchema _schema;
- private ExecutableDocument _subscription;
+ private ExecutableDocument _mutation;
+ private ExecutableDocument _query;
+ private ISchema _schema;
+ private ExecutableDocument _subscription;
- [Params(1)] public int ExecutionCount { get; set; } = 1;
+ [Params(1)] public int ExecutionCount { get; set; } = 1;
- [Benchmark]
- public async Task Mutation_with_defaults()
+ [Benchmark]
+ public async Task Mutation_with_defaults()
+ {
+ for (var i = 0; i < ExecutionCount; i++)
{
- for (var i = 0; i < ExecutionCount; i++)
+ var result = await Executor.ExecuteAsync(new ExecutionOptions
{
- var result = await Executor.ExecuteAsync(new ExecutionOptions
- {
- Document = _mutation,
- Schema = _schema
- });
-
- AssertResult(result.Errors);
- }
+ Document = _mutation,
+ Schema = _schema
+ });
+
+ AssertResult(result.Errors);
}
+ }
- [Benchmark]
- public async Task Mutation_without_validation()
+ [Benchmark]
+ public async Task Mutation_without_validation()
+ {
+ for (var i = 0; i < ExecutionCount; i++)
{
- for (var i = 0; i < ExecutionCount; i++)
+ var result = await Executor.ExecuteAsync(new ExecutionOptions
{
- var result = await Executor.ExecuteAsync(new ExecutionOptions
- {
- Document = _mutation,
- Schema = _schema,
- Validate = null
- });
-
- AssertResult(result.Errors);
- }
+ Document = _mutation,
+ Schema = _schema,
+ Validate = null
+ });
+
+ AssertResult(result.Errors);
}
+ }
- [Benchmark]
- public async Task Query_with_defaults()
+ [Benchmark]
+ public async Task Query_with_defaults()
+ {
+ for (var i = 0; i < ExecutionCount; i++)
{
- for (var i = 0; i < ExecutionCount; i++)
+ var result = await Executor.ExecuteAsync(new ExecutionOptions
{
- var result = await Executor.ExecuteAsync(new ExecutionOptions
- {
- Document = _query,
- Schema = _schema
- });
-
- AssertResult(result.Errors);
- }
+ Document = _query,
+ Schema = _schema
+ });
+
+ AssertResult(result.Errors);
}
+ }
- [Benchmark(Baseline = true)]
- public async Task Query_without_validation()
+ [Benchmark(Baseline = true)]
+ public async Task Query_without_validation()
+ {
+ for (var i = 0; i < ExecutionCount; i++)
{
- for (var i = 0; i < ExecutionCount; i++)
+ var result = await Executor.ExecuteAsync(new ExecutionOptions
{
- var result = await Executor.ExecuteAsync(new ExecutionOptions
- {
- Document = _query,
- Schema = _schema,
- Validate = null
- });
-
- AssertResult(result.Errors);
- }
- }
+ Document = _query,
+ Schema = _schema,
+ Validate = null
+ });
- [GlobalSetup]
- public void Setup()
- {
- _schema = Utils.InitializeSchema();
- _query = Utils.InitializeQuery();
- _mutation = Utils.InitializeMutation();
- _subscription = Utils.InitializeSubscription();
+ AssertResult(result.Errors);
}
+ }
- [Benchmark]
- public async Task Subscribe_with_defaults()
+ [GlobalSetup]
+ public void Setup()
+ {
+ _schema = Utils.InitializeSchema().Result;
+ _query = Utils.InitializeQuery();
+ _mutation = Utils.InitializeMutation();
+ _subscription = Utils.InitializeSubscription();
+ }
+
+ [Benchmark]
+ public async Task Subscribe_with_defaults()
+ {
+ for (var i = 0; i < ExecutionCount; i++)
{
- for (var i = 0; i < ExecutionCount; i++)
+ var cts = new CancellationTokenSource();
+ var result = await Executor.SubscribeAsync(new ExecutionOptions
{
- var cts = new CancellationTokenSource();
- var result = await Executor.SubscribeAsync(new ExecutionOptions
- {
- Document = _subscription,
- Schema = _schema
- }, cts.Token);
-
- AssertResult(result.Errors);
- cts.Cancel();
- }
+ Document = _subscription,
+ Schema = _schema
+ }, cts.Token);
+
+ AssertResult(result.Errors);
+ cts.Cancel();
}
+ }
- [Benchmark]
- public async Task Subscribe_with_defaults_and_get_value()
+ [Benchmark]
+ public async Task Subscribe_with_defaults_and_get_value()
+ {
+ for (var i = 0; i < ExecutionCount; i++)
{
- for (var i = 0; i < ExecutionCount; i++)
+ var cts = new CancellationTokenSource();
+ var result = await Executor.SubscribeAsync(new ExecutionOptions
{
- var cts = new CancellationTokenSource();
- var result = await Executor.SubscribeAsync(new ExecutionOptions
- {
- Document = _subscription,
- Schema = _schema
- }, cts.Token);
-
- AssertResult(result.Errors);
-
- var value = await result.Source.Reader.ReadAsync(cts.Token);
- AssertResult(value.Errors);
- cts.Cancel();
- }
+ Document = _subscription,
+ Schema = _schema
+ }, cts.Token);
+
+ AssertResult(result.Errors);
+
+ var value = await result.Source.Reader.ReadAsync(cts.Token);
+ AssertResult(value.Errors);
+ cts.Cancel();
}
+ }
- [Benchmark]
- public async Task Subscribe_without_validation()
+ [Benchmark]
+ public async Task Subscribe_without_validation()
+ {
+ for (var i = 0; i < ExecutionCount; i++)
{
- for (var i = 0; i < ExecutionCount; i++)
+ var cts = new CancellationTokenSource();
+ var result = await Executor.SubscribeAsync(new ExecutionOptions
{
- var cts = new CancellationTokenSource();
- var result = await Executor.SubscribeAsync(new ExecutionOptions
- {
- Document = _subscription,
- Schema = _schema,
- Validate = null
- }, cts.Token);
-
- AssertResult(result.Errors);
- cts.Cancel();
- }
- }
+ Document = _subscription,
+ Schema = _schema,
+ Validate = null
+ }, cts.Token);
- private static void AssertResult(IEnumerable errors)
- {
- if (errors != null && errors.Any())
- throw new InvalidOperationException(
- $"Execution failed. {string.Join("", errors.Select(e => e.Message))}");
+ AssertResult(result.Errors);
+ cts.Cancel();
}
}
+
+ private static void AssertResult(IEnumerable errors)
+ {
+ if (errors != null && errors.Any())
+ throw new InvalidOperationException(
+ $"Execution failed. {string.Join("", errors.Select(e => e.Message))}");
+ }
}
\ No newline at end of file
diff --git a/benchmarks/graphql.benchmarks/LanguageLexerBenchmarks.cs b/benchmarks/graphql.benchmarks/LanguageLexerBenchmarks.cs
index b72d9de6c..f407153bd 100644
--- a/benchmarks/graphql.benchmarks/LanguageLexerBenchmarks.cs
+++ b/benchmarks/graphql.benchmarks/LanguageLexerBenchmarks.cs
@@ -5,44 +5,42 @@
using GraphQLParser;
using Tanka.GraphQL.Introspection;
-namespace Tanka.GraphQL.Benchmarks
-{
- [Orderer(SummaryOrderPolicy.FastestToSlowest)]
- [RankColumn]
- [MemoryDiagnoser]
- [MarkdownExporterAttribute.GitHub]
- public class LanguageLexerBenchmarks
- {
- public string SimpleQuery { get; set; }
+namespace Tanka.GraphQL.Benchmarks;
- public string IntrospectionQuery { get; set; }
+[Orderer(SummaryOrderPolicy.FastestToSlowest)]
+[RankColumn]
+[MemoryDiagnoser]
+[MarkdownExporterAttribute.GitHub]
+public class LanguageLexerBenchmarks
+{
+ public string IntrospectionQuery { get; set; }
- public Memory IntrospectionQueryMemory { get; set; }
+ public Memory IntrospectionQueryMemory { get; set; }
+ public string SimpleQuery { get; set; }
- [GlobalSetup]
- public void Setup()
- {
- IntrospectionQuery = Introspect.DefaultQuery;
- IntrospectionQueryMemory = new Memory(Encoding.UTF8.GetBytes(IntrospectionQuery));
- SimpleQuery = "query { field }";
- }
+ [GlobalSetup]
+ public void Setup()
+ {
+ IntrospectionQuery = Introspect.DefaultQuery;
+ IntrospectionQueryMemory = new Memory(Encoding.UTF8.GetBytes(IntrospectionQuery));
+ SimpleQuery = "query { field }";
+ }
- [Benchmark(Baseline = true)]
- public void GraphQL_dotnet_Lexer_IntrospectionQuery()
- {
- var token = Lexer.Lex(IntrospectionQuery);
- while (token.Kind != TokenKind.EOF)
- token = Lexer.Lex(IntrospectionQuery, token.End);
- }
+ [Benchmark(Baseline = true)]
+ public void GraphQL_dotnet_Lexer_IntrospectionQuery()
+ {
+ var token = Lexer.Lex(IntrospectionQuery);
+ while (token.Kind != TokenKind.EOF)
+ token = Lexer.Lex(IntrospectionQuery, token.End);
+ }
- [Benchmark]
- public void Tanka_GraphQL_Lexer_IntrospectionQuery()
+ [Benchmark]
+ public void Tanka_GraphQL_Lexer_IntrospectionQuery()
+ {
+ var lexer = Language.Lexer.Create(IntrospectionQueryMemory.Span);
+ while (lexer.Advance())
{
- var lexer = Language.Lexer.Create(IntrospectionQueryMemory.Span);
- while (lexer.Advance())
- {
- //noop
- }
+ //noop
}
}
}
\ No newline at end of file
diff --git a/benchmarks/graphql.benchmarks/LanguageParserBenchmarks.cs b/benchmarks/graphql.benchmarks/LanguageParserBenchmarks.cs
index 54c3272c6..77e46a8e0 100644
--- a/benchmarks/graphql.benchmarks/LanguageParserBenchmarks.cs
+++ b/benchmarks/graphql.benchmarks/LanguageParserBenchmarks.cs
@@ -3,47 +3,45 @@
using System.Text;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Order;
-using GraphQLParser;
using Tanka.GraphQL.Introspection;
using Tanka.GraphQL.Language;
-using Lexer = GraphQLParser.Lexer;
+using Parser = GraphQLParser.Parser;
-namespace Tanka.GraphQL.Benchmarks
+namespace Tanka.GraphQL.Benchmarks;
+
+[Orderer(SummaryOrderPolicy.FastestToSlowest)]
+[RankColumn]
+[MemoryDiagnoser]
+[MarkdownExporterAttribute.GitHub]
+public class LanguageParserBenchmarks
{
- [Orderer(SummaryOrderPolicy.FastestToSlowest)]
- [RankColumn]
- [MemoryDiagnoser]
- [MarkdownExporterAttribute.GitHub]
- public class LanguageParserBenchmarks
+ public Memory IntrospectionQueryMemory;
+ public string IntrospectionQuery { get; set; }
+
+ [GlobalSetup]
+ public void Setup()
{
- public Memory IntrospectionQueryMemory;
- public string IntrospectionQuery { get; set; }
+ IntrospectionQuery = Introspect.DefaultQuery;
+ IntrospectionQueryMemory = new Memory(Encoding.UTF8.GetBytes(IntrospectionQuery));
+ var _ = Constants.Space;
+ }
- [GlobalSetup]
- public void Setup()
- {
- IntrospectionQuery = Introspect.DefaultQuery;
- IntrospectionQueryMemory = new Memory(Encoding.UTF8.GetBytes(IntrospectionQuery));
- var _ = Constants.Space;
- }
+ [Benchmark(Baseline = true)]
+ public void GraphQL_dotnet_Parser_IntrospectionQuery()
+ {
+ var document = Parser.Parse(IntrospectionQuery);
- [Benchmark(Baseline = true)]
- public void GraphQL_dotnet_Parser_IntrospectionQuery()
- {
- var document = GraphQLParser.Parser.Parse(IntrospectionQuery);
-
- if (document.Definitions?.Any() == false)
- throw new InvalidOperationException("Failed");
- }
+ if (document.Definitions?.Any() == false)
+ throw new InvalidOperationException("Failed");
+ }
- [Benchmark]
- public void Tanka_GraphQL_Parser_IntrospectionQuery()
- {
- var parser = Language.Parser.Create(IntrospectionQueryMemory.Span);
- var document = parser.ParseExecutableDocument();
+ [Benchmark]
+ public void Tanka_GraphQL_Parser_IntrospectionQuery()
+ {
+ var parser = Language.Parser.Create(IntrospectionQueryMemory.Span);
+ var document = parser.ParseExecutableDocument();
- if (document.OperationDefinitions == null || !document.OperationDefinitions.Any())
- throw new InvalidOperationException("Failed");
- }
+ if (document.OperationDefinitions == null || !document.OperationDefinitions.Any())
+ throw new InvalidOperationException("Failed");
}
}
\ No newline at end of file
diff --git a/benchmarks/graphql.benchmarks/MethodBenchmarks.cs b/benchmarks/graphql.benchmarks/MethodBenchmarks.cs
index 8027414fe..2a3fdfe56 100644
--- a/benchmarks/graphql.benchmarks/MethodBenchmarks.cs
+++ b/benchmarks/graphql.benchmarks/MethodBenchmarks.cs
@@ -1,48 +1,42 @@
using System;
-using System.Collections.Generic;
using System.Text;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Order;
-using Tanka.GraphQL.Language;
-using Tanka.GraphQL.Language.Internal;
-namespace Tanka.GraphQL.Benchmarks
+namespace Tanka.GraphQL.Benchmarks;
+
+[Orderer(SummaryOrderPolicy.FastestToSlowest)]
+[RankColumn]
+[MemoryDiagnoser]
+[MarkdownExporterAttribute.GitHub]
+public class MethodBenchmarks
{
- [Orderer(SummaryOrderPolicy.FastestToSlowest)]
- [RankColumn]
- [MemoryDiagnoser]
- [MarkdownExporterAttribute.GitHub]
- public class MethodBenchmarks
- {
- [GlobalSetup]
- public void Setup()
- {
- NameCount = 10_000;
- Data = new ReadOnlyMemory(Encoding.UTF8.GetBytes("test test test"));
- }
+ public ReadOnlyMemory Data { get; set; }
- public ReadOnlyMemory Data { get; set; }
+ public int NameCount { get; set; }
- public int NameCount { get; set; }
+ [GlobalSetup]
+ public void Setup()
+ {
+ NameCount = 10_000;
+ Data = new ReadOnlyMemory(Encoding.UTF8.GetBytes("test test test"));
+ }
- [Benchmark(Baseline = true)]
- public void Base()
+ [Benchmark(Baseline = true)]
+ public void Base()
+ {
+ for (var i = 0; i < NameCount; i++)
{
- for (int i = 0; i < NameCount; i++)
- {
- var str = Encoding.UTF8.GetString(Data.Span);
- }
+ var str = Encoding.UTF8.GetString(Data.Span);
}
+ }
- [Benchmark()]
- public void Cached()
- {
- var str = string.Empty;
- for (int i = 0; i < NameCount; i++)
- {
- if (str == string.Empty)
- str = Encoding.UTF8.GetString(Data.Span);
- }
- }
+ [Benchmark]
+ public void Cached()
+ {
+ var str = string.Empty;
+ for (var i = 0; i < NameCount; i++)
+ if (str == string.Empty)
+ str = Encoding.UTF8.GetString(Data.Span);
}
}
\ No newline at end of file
diff --git a/benchmarks/graphql.benchmarks/Program.cs b/benchmarks/graphql.benchmarks/Program.cs
index 059b476b6..0ae8968e4 100644
--- a/benchmarks/graphql.benchmarks/Program.cs
+++ b/benchmarks/graphql.benchmarks/Program.cs
@@ -2,28 +2,26 @@
using BenchmarkDotNet.Jobs;
using BenchmarkDotNet.Running;
-namespace Tanka.GraphQL.Benchmarks
+namespace Tanka.GraphQL.Benchmarks;
+
+public class Program
{
- public class Program
+ private static void Main(string[] args)
{
- private static void Main(string[] args)
- {
- var runner = BenchmarkSwitcher
- .FromAssembly(typeof(Program).Assembly);
-
- if (args.Length == 0)
- runner.RunAll(GetGlobalConfig());
- else
- {
- runner.Run(args, GetGlobalConfig());
- }
+ var runner = BenchmarkSwitcher
+ .FromAssembly(typeof(Program).Assembly);
- }
+ if (args.Length == 0)
+ runner.RunAll(GetGlobalConfig());
+ else
+ runner.Run(args, GetGlobalConfig());
+ }
- static IConfig GetGlobalConfig()
- => DefaultConfig.Instance
- .WithArtifactsPath("artifacts/benchmarks")
- .AddJob(Job.Default
- .AsDefault());
+ private static IConfig GetGlobalConfig()
+ {
+ return DefaultConfig.Instance
+ .WithArtifactsPath("artifacts/benchmarks")
+ .AddJob(Job.Default
+ .AsDefault());
}
}
\ No newline at end of file
diff --git a/benchmarks/graphql.benchmarks/RealWorldSchemas/ParseGitHubSchemaFacts.cs b/benchmarks/graphql.benchmarks/RealWorldSchemas/ParseGitHubSchemaFacts.cs
index 6835fdbad..ba6ad1ae9 100644
--- a/benchmarks/graphql.benchmarks/RealWorldSchemas/ParseGitHubSchemaFacts.cs
+++ b/benchmarks/graphql.benchmarks/RealWorldSchemas/ParseGitHubSchemaFacts.cs
@@ -3,33 +3,31 @@
using System.Linq;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Order;
+using Tanka.GraphQL.Language;
-namespace Tanka.GraphQL.Benchmarks.RealWorldSchemas
+namespace Tanka.GraphQL.Benchmarks.RealWorldSchemas;
+
+[Orderer(SummaryOrderPolicy.FastestToSlowest)]
+[RankColumn]
+[MemoryDiagnoser]
+[MarkdownExporterAttribute.GitHub]
+public class ParseGitHubSchemaBenchmark
{
- [Orderer(SummaryOrderPolicy.FastestToSlowest)]
- [RankColumn]
- [MemoryDiagnoser]
- [MarkdownExporterAttribute.GitHub]
- public class ParseGitHubSchemaBenchmark
- {
- public byte[] GitHubBytes { get; private set; }
+ public byte[] GitHubBytes { get; private set; }
- [GlobalSetup]
- public void Setup()
- {
- GitHubBytes = File.ReadAllBytes("RealWorldSchemas/github.graphql");
- }
+ [GlobalSetup]
+ public void Setup()
+ {
+ GitHubBytes = File.ReadAllBytes("RealWorldSchemas/github.graphql");
+ }
- [Benchmark]
- public void GitHub()
- {
- var parser = Language.Parser.Create(GitHubBytes);
- var typeSystem = parser.ParseTypeSystemDocument();
+ [Benchmark]
+ public void GitHub()
+ {
+ var parser = Parser.Create(GitHubBytes);
+ var typeSystem = parser.ParseTypeSystemDocument();
- if (typeSystem.TypeDefinitions == null || !typeSystem.TypeDefinitions.Any())
- {
- throw new Exception("It has types");
- }
- }
+ if (typeSystem.TypeDefinitions == null || !typeSystem.TypeDefinitions.Any())
+ throw new Exception("It has types");
}
}
\ No newline at end of file
diff --git a/benchmarks/graphql.benchmarks/SingleValueEventChannel.cs b/benchmarks/graphql.benchmarks/SingleValueEventChannel.cs
index c245d4fa5..5d74dafa7 100644
--- a/benchmarks/graphql.benchmarks/SingleValueEventChannel.cs
+++ b/benchmarks/graphql.benchmarks/SingleValueEventChannel.cs
@@ -2,15 +2,14 @@
using Tanka.GraphQL.Channels;
using Tanka.GraphQL.ValueResolution;
-namespace Tanka.GraphQL.Benchmarks
+namespace Tanka.GraphQL.Benchmarks;
+
+public class SingleValueEventChannel : EventChannel
{
- public class SingleValueEventChannel : EventChannel
+ public override void OnSubscribed(ISubscriberResult subscription)
{
- public override void OnSubscribed(ISubscriberResult subscription)
- {
- subscription.WriteAsync("value", CancellationToken.None)
- .AsTask()
- .Wait();
- }
+ subscription.WriteAsync("value", CancellationToken.None)
+ .AsTask()
+ .Wait();
}
}
\ No newline at end of file
diff --git a/benchmarks/graphql.benchmarks/Utils.cs b/benchmarks/graphql.benchmarks/Utils.cs
index 9ce91ceaf..ff9790555 100644
--- a/benchmarks/graphql.benchmarks/Utils.cs
+++ b/benchmarks/graphql.benchmarks/Utils.cs
@@ -1,20 +1,18 @@
using System.Threading.Tasks;
+using Tanka.GraphQL.Language;
using Tanka.GraphQL.Language.Nodes;
-using Tanka.GraphQL.ValueResolution;
-using Tanka.GraphQL.SchemaBuilding;
-using Tanka.GraphQL.SDL;
-using Tanka.GraphQL.Tools;
using Tanka.GraphQL.TypeSystem;
+using Tanka.GraphQL.ValueResolution;
+
+namespace Tanka.GraphQL.Benchmarks;
-namespace Tanka.GraphQL.Benchmarks
+public static class Utils
{
- public static class Utils
+ public static Task InitializeSchema()
{
- public static ISchema InitializeSchema()
- {
- var events = new SingleValueEventChannel();
- var builder = new SchemaBuilder()
- .Sdl(Parser.ParseTypeSystemDocument(
+ var events = new SingleValueEventChannel();
+ var builder = new SchemaBuilder()
+ .Add(
@"
type Query {
simple: String
@@ -33,63 +31,58 @@ type Subscription {
mutation: Mutation
subscription: Subscription
}
- "));
+ ");
- var resolvers = new ObjectTypeMap
+ var resolvers = new ResolversMap
+ {
{
+ "Query", new FieldResolversMap
{
- "Query", new FieldResolversMap
- {
- {"simple", context => new ValueTask(Resolve.As("value"))}
- }
- },
+ { "simple", context => new ValueTask(Resolve.As("value")) }
+ }
+ },
+ {
+ "Mutation", new FieldResolversMap
{
- "Mutation", new FieldResolversMap
- {
- {"simple", context => new ValueTask(Resolve.As("value"))}
- }
- },
+ { "simple", context => new ValueTask(Resolve.As("value")) }
+ }
+ },
+ {
+ "Subscription", new FieldResolversMap
{
- "Subscription", new FieldResolversMap()
{
- {
- "simple",
- (context, unsubscribe) => ResolveSync.Subscribe(events, unsubscribe),
- context => new ValueTask(Resolve.As(context.ObjectValue))}
+ "simple",
+ (context, unsubscribe) => ResolveSync.Subscribe(events, unsubscribe),
+ context => new ValueTask(Resolve.As(context.ObjectValue))
}
}
- };
-
- var schema = SchemaTools.MakeExecutableSchema(
- builder,
- resolvers,
- resolvers);
+ }
+ };
- return schema;
- }
+ return builder.Build(resolvers, resolvers);
+ }
- public static ExecutableDocument InitializeQuery()
- {
- return Parser.ParseDocument(@"
+ public static ExecutableDocument InitializeQuery()
+ {
+ return @"
{
simple
-}");
- }
+}";
+ }
- public static ExecutableDocument InitializeMutation()
- {
- return Parser.ParseDocument(@"
+ public static ExecutableDocument InitializeMutation()
+ {
+ return @"
mutation {
simple
-}");
- }
+}";
+ }
- public static ExecutableDocument InitializeSubscription()
- {
- return Parser.ParseDocument(@"
+ public static ExecutableDocument InitializeSubscription()
+ {
+ return @"
subscription {
simple
-}");
- }
+}";
}
}
\ No newline at end of file
diff --git a/benchmarks/graphql.benchmarks/ValidationBenchmarks.cs b/benchmarks/graphql.benchmarks/ValidationBenchmarks.cs
index de46333da..fff4831c3 100644
--- a/benchmarks/graphql.benchmarks/ValidationBenchmarks.cs
+++ b/benchmarks/graphql.benchmarks/ValidationBenchmarks.cs
@@ -3,42 +3,56 @@
using System.Linq;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Order;
-
using Tanka.GraphQL.Language.Nodes;
using Tanka.GraphQL.Language.Validation;
using Tanka.GraphQL.Language.Visitors;
using Tanka.GraphQL.TypeSystem;
using Tanka.GraphQL.Validation;
-namespace Tanka.GraphQL.Benchmarks
+namespace Tanka.GraphQL.Benchmarks;
+
+[Orderer(SummaryOrderPolicy.FastestToSlowest)]
+[MemoryDiagnoser]
+[MarkdownExporterAttribute.GitHub]
+public class ValidationBenchmarks
{
- [Orderer(SummaryOrderPolicy.FastestToSlowest)]
- [MemoryDiagnoser]
- [MarkdownExporterAttribute.GitHub]
- public class ValidationBenchmarks
- {
- private List _comparisonRules;
- private List _defaultRulesMap;
- private ExecutableDocument _query;
- private ExecutableDocument _query2;
- private ISchema _schema;
+ private List _comparisonRules;
+ private List _defaultRulesMap;
+ private ExecutableDocument _query;
+ private ExecutableDocument _query2;
+ private ISchema _schema;
- [GlobalSetup]
- public void Setup()
+ [GlobalSetup]
+ public void Setup()
+ {
+ _schema = Utils.InitializeSchema().Result;
+ _query = Utils.InitializeQuery();
+ _defaultRulesMap = ExecutionRules.All.ToList();
+ _comparisonRules = new List
{
- _schema = Utils.InitializeSchema();
- _query = Utils.InitializeQuery();
- _defaultRulesMap = ExecutionRules.All.ToList();
- _comparisonRules = new List
- {
- ExecutionRules.R5211OperationNameUniqueness()
- };
+ ExecutionRules.R5211OperationNameUniqueness()
+ };
- _query2 = @"query Q1 { field1, field2, field3 { field1 field2 }} query Q2 { field1 }";
- }
+ _query2 = @"query Q1 { field1, field2, field3 { field1 field2 }} query Q2 { field1 }";
+ }
+
+ [Benchmark(Baseline = true)]
+ public void Tanka_1()
+ {
+ var result = Validator.Validate(
+ _comparisonRules,
+ _schema,
+ _query);
+
+ if (!result.IsValid)
+ throw new InvalidOperationException(
+ $"Validation failed. {result}");
+ }
- [Benchmark(Baseline = true)]
- public void Tanka_1()
+ [Benchmark(Baseline = false)]
+ public void Tanka_1_1000()
+ {
+ for (var i = 0; i < 1000; i++)
{
var result = Validator.Validate(
_comparisonRules,
@@ -49,79 +63,63 @@ public void Tanka_1()
throw new InvalidOperationException(
$"Validation failed. {result}");
}
+ }
- [Benchmark(Baseline = false)]
- public void Tanka_1_1000()
- {
- for (var i = 0; i < 1000; i++)
+ [Benchmark]
+ public void Tanka_2()
+ {
+ var rule = new OperationNameUniquenessRule();
+ var walker = new ReadOnlyExecutionDocumentWalker(
+ new ExecutionDocumentWalkerOptions
{
- var result = Validator.Validate(
- _comparisonRules,
- _schema,
- _query);
-
- if (!result.IsValid)
- throw new InvalidOperationException(
- $"Validation failed. {result}");
+ ExecutableDocument =
+ {
+ rule
+ },
+ OperationDefinition =
+ {
+ rule
+ }
}
- }
+ );
- [Benchmark]
- public void Tanka_2()
+ walker.Visit(_query2);
+ }
+
+ [Benchmark]
+ public void Tanka_2__1000()
+ {
+ for (var i = 0; i < 1000; i++)
{
- var rule = new OperationNameUniquenessRule();
+ var rule = new OperationNameUniquenessRule();
var walker = new ReadOnlyExecutionDocumentWalker(
- new ExecutionDocumentWalkerOptions()
+ new ExecutionDocumentWalkerOptions
+ {
+ ExecutableDocument =
{
- ExecutableDocument =
- {
- rule
- },
- OperationDefinition =
- {
- rule
- }
- }
- );
-
- walker.Visit(_query2);
- }
-
- [Benchmark]
- public void Tanka_2__1000()
- {
- for (var i = 0; i < 1000; i++)
- {
- var rule = new OperationNameUniquenessRule();
- var walker = new ReadOnlyExecutionDocumentWalker(
- new ExecutionDocumentWalkerOptions()
+ rule
+ },
+ OperationDefinition =
{
- ExecutableDocument =
- {
- rule
- },
- OperationDefinition =
- {
- rule
- }
+ rule
}
- );
+ }
+ );
- walker.Visit(_query2);
- }
+ walker.Visit(_query2);
}
+ }
- //[Benchmark]
- public void Validate_with_defaults()
- {
- var result = Validator.Validate(
- _defaultRulesMap,
- _schema,
- _query);
+ //[Benchmark]
+ public void Validate_with_defaults()
+ {
+ var result = Validator.Validate(
+ _defaultRulesMap,
+ _schema,
+ _query);
- if (!result.IsValid)
- throw new InvalidOperationException(
- $"Validation failed. {result}");
- }
+ if (!result.IsValid)
+ throw new InvalidOperationException(
+ $"Validation failed. {result}");
}
}
\ No newline at end of file
diff --git a/benchmarks/graphql.benchmarks/graphql.benchmarks.csproj b/benchmarks/graphql.benchmarks/graphql.benchmarks.csproj
index 0e585ed24..7c618f3a5 100644
--- a/benchmarks/graphql.benchmarks/graphql.benchmarks.csproj
+++ b/benchmarks/graphql.benchmarks/graphql.benchmarks.csproj
@@ -2,7 +2,7 @@
Exe
- net5.0
+ net6.0
graphql.benchmarks
Tanka.GraphQL.Benchmarks
false
diff --git a/build.ps1 b/build.ps1
index ae6f2d171..bca206980 100644
--- a/build.ps1
+++ b/build.ps1
@@ -1,6 +1,6 @@
param (
[string]$Output = "./artifacts",
- [string]$CurrentBranch = $Env:BUILD_SOURCEBRANCH
+ [string]$CurrentBranch =''
)
# Utils
diff --git a/dev/GraphQL.Dev.Reviews/Controllers/GraphQLController.cs b/dev/GraphQL.Dev.Reviews/Controllers/GraphQLController.cs
index 301703a25..a16d8177e 100644
--- a/dev/GraphQL.Dev.Reviews/Controllers/GraphQLController.cs
+++ b/dev/GraphQL.Dev.Reviews/Controllers/GraphQLController.cs
@@ -1,51 +1,48 @@
using System.Collections.Generic;
-using System.Net;
using System.Threading.Tasks;
-using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Tanka.GraphQL;
using Tanka.GraphQL.Server;
-namespace GraphQL.Dev.Reviews.Controllers
+namespace GraphQL.Dev.Reviews.Controllers;
+
+[ApiController]
+[Route("graphql")]
+public class GraphQLController : ControllerBase
{
- [ApiController]
- [Route("graphql")]
- public class GraphQLController : ControllerBase
+ private readonly ILogger _logger;
+ private readonly IQueryStreamService _query;
+
+ public GraphQLController(
+ IQueryStreamService query,
+ ILogger logger)
{
- private readonly IQueryStreamService _query;
- private readonly ILogger _logger;
-
- public GraphQLController(
- IQueryStreamService query,
- ILogger logger)
- {
- _query = query;
- _logger = logger;
- }
-
- [HttpPost]
- public async Task> Get(OperationRequest operation)
- {
- var stream = await _query.QueryAsync(
- new Query()
- {
- Document = Parser.ParseDocument(operation.Query),
- Variables = operation.Variables,
- OperationName = operation.OperationName
- }, HttpContext.RequestAborted);
- var result = await stream.Reader.ReadAsync(HttpContext.RequestAborted);
-
- return Ok(result);
- }
+ _query = query;
+ _logger = logger;
}
- public class OperationRequest
+ [HttpPost]
+ public async Task> Get(OperationRequest operation)
{
- public string OperationName { get; set; }
+ var stream = await _query.QueryAsync(
+ new Query
+ {
+ Document = operation.Query,
+ Variables = operation.Variables,
+ OperationName = operation.OperationName
+ }, HttpContext.RequestAborted);
+ var result = await stream.Reader.ReadAsync(HttpContext.RequestAborted);
- public string Query { get; set; }
-
- public Dictionary Variables { get; set; }
+ return Ok(result);
}
+}
+
+public class OperationRequest
+{
+ public string OperationName { get; set; }
+
+ public string Query { get; set; }
+
+ public Dictionary Variables { get; set; }
}
\ No newline at end of file
diff --git a/dev/GraphQL.Dev.Reviews/GraphQL.Dev.Reviews.csproj b/dev/GraphQL.Dev.Reviews/GraphQL.Dev.Reviews.csproj
index eb16c84d4..99c228e77 100644
--- a/dev/GraphQL.Dev.Reviews/GraphQL.Dev.Reviews.csproj
+++ b/dev/GraphQL.Dev.Reviews/GraphQL.Dev.Reviews.csproj
@@ -1,7 +1,7 @@
- net5.0
+ net6.0
diff --git a/dev/GraphQL.Dev.Reviews/Program.cs b/dev/GraphQL.Dev.Reviews/Program.cs
index 5530f13f0..dbdd28fdb 100644
--- a/dev/GraphQL.Dev.Reviews/Program.cs
+++ b/dev/GraphQL.Dev.Reviews/Program.cs
@@ -1,26 +1,18 @@
using Microsoft.AspNetCore.Hosting;
-using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
-using Microsoft.Extensions.Logging;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading.Tasks;
-namespace GraphQL.Dev.Reviews
+namespace GraphQL.Dev.Reviews;
+
+public class Program
{
- public class Program
+ public static void Main(string[] args)
{
- public static void Main(string[] args)
- {
- CreateHostBuilder(args).Build().Run();
- }
+ CreateHostBuilder(args).Build().Run();
+ }
- public static IHostBuilder CreateHostBuilder(string[] args) =>
- Host.CreateDefaultBuilder(args)
- .ConfigureWebHostDefaults(webBuilder =>
- {
- webBuilder.UseStartup();
- });
+ public static IHostBuilder CreateHostBuilder(string[] args)
+ {
+ return Host.CreateDefaultBuilder(args)
+ .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup(); });
}
-}
+}
\ No newline at end of file
diff --git a/dev/GraphQL.Dev.Reviews/Properties/launchSettings.json b/dev/GraphQL.Dev.Reviews/Properties/launchSettings.json
index c9ca74200..c00907095 100644
--- a/dev/GraphQL.Dev.Reviews/Properties/launchSettings.json
+++ b/dev/GraphQL.Dev.Reviews/Properties/launchSettings.json
@@ -27,4 +27,4 @@
}
}
}
-}
+}
\ No newline at end of file
diff --git a/dev/GraphQL.Dev.Reviews/SchemaFactory.cs b/dev/GraphQL.Dev.Reviews/SchemaFactory.cs
index 36ce5b063..99810e45c 100644
--- a/dev/GraphQL.Dev.Reviews/SchemaFactory.cs
+++ b/dev/GraphQL.Dev.Reviews/SchemaFactory.cs
@@ -4,19 +4,17 @@
using System.Threading.Tasks;
using Tanka.GraphQL;
using Tanka.GraphQL.Extensions.ApolloFederation;
-using Tanka.GraphQL.SchemaBuilding;
-using Tanka.GraphQL.SDL;
-using Tanka.GraphQL.Tools;
+using Tanka.GraphQL.Language.Nodes.TypeSystem;
using Tanka.GraphQL.TypeSystem;
using Tanka.GraphQL.ValueResolution;
-namespace GraphQL.Dev.Reviews
+namespace GraphQL.Dev.Reviews;
+
+public static class SchemaFactory
{
- public static class SchemaFactory
+ public static async ValueTask Create()
{
- public static async ValueTask Create()
- {
- var typeDefs = @"
+ var typeDefs = @"
type Review @key(fields: ""id"") {
id: ID!
body: String
@@ -38,187 +36,181 @@ type Product @key(fields: ""upc"") @extends {
type Query {
}
";
- var builder = new SchemaBuilder()
- .AddFederationDirectives();
-
- await builder.SdlAsync(typeDefs);
+ var builder = new SchemaBuilder()
+ .Add(typeDefs);
- builder.UseResolversAndSubscribers(
- new ObjectTypeMap
+ var schema = await builder.BuildSubgraph(new FederatedSchemaBuildOptions
+ {
+ SchemaBuildOptions = new SchemaBuildOptions
+ {
+ Resolvers = new ResolversMap
{
- ["User"] = new FieldResolversMap
+ ["User"] = new()
{
- {"id", Resolve.PropertyOf(u => u.ID)},
- {"username", UserUsername},
- {"reviews", UserReviews}
+ { "id", Resolve.PropertyOf(u => u.ID) },
+ { "username", UserUsername },
+ { "reviews", UserReviews }
},
- ["Review"] = new FieldResolversMap
+ ["Review"] = new()
{
- {"id", Resolve.PropertyOf(r => r.ID)},
- {"body", Resolve.PropertyOf(r => r.Body)},
- {"author", ReviewAuthor},
- {"product", Resolve.PropertyOf(r => r.Product)}
+ { "id", Resolve.PropertyOf(r => r.ID) },
+ { "body", Resolve.PropertyOf(r => r.Body) },
+ { "author", ReviewAuthor },
+ { "product", Resolve.PropertyOf(r => r.Product) }
},
- ["Product"] = new FieldResolversMap
+ ["Product"] = new()
{
- {"upc", Resolve.PropertyOf(p => p.Upc)},
- {"reviews", ProductReviews}
+ { "upc", Resolve.PropertyOf(p => p.Upc) },
+ { "reviews", ProductReviews }
}
- });
+ }
+ },
+ ReferenceResolvers = new DictionaryReferenceResolversMap
+ {
+ ["User"] = UserReference,
+ ["Product"] = ProductReference
+ }
+ });
- var federationBuilder = Federation
- .ServiceFrom(builder.Build(),
- new DictionaryReferenceResolversMap()
- {
- ["User"] = UserReference,
- ["Product"] = ProductReference
- });
+ return schema;
+ }
- return SchemaTools.MakeExecutableSchemaWithIntrospection(federationBuilder);
- }
+ private static ValueTask UserUsername(IResolverContext context)
+ {
+ var user = (User)context.ObjectValue;
- private static ValueTask UserUsername(IResolverContext context)
- {
- var user = (User) context.ObjectValue;
+ return ResolveSync.As(user.Username);
+ }
- return ResolveSync.As(user.Username);
- }
+ private static async ValueTask ProductReference(
+ IResolverContext context, TypeDefinition type, IReadOnlyDictionary representation)
+ {
+ await Task.Delay(0);
- private static async ValueTask ProductReference(
- IResolverContext context, INamedType type, IReadOnlyDictionary representation)
+ var upc = representation["upc"].ToString();
+ var product = new Product
{
- await Task.Delay(0);
+ Upc = upc
+ };
- var upc = representation["upc"].ToString();
- var product = new Product
- {
- Upc = upc
- };
+ return new ResolveReferenceResult(type, product);
+ }
- return new ResolveReferenceResult(type, product);
- }
+ private static ValueTask ProductReviews(IResolverContext context)
+ {
+ var product = (Product)context.ObjectValue;
+ var reviews = Db.Reviews
+ .Where(r => r.Value.Product.Upc == product.Upc)
+ .Select(p => p.Value);
- private static ValueTask ProductReviews(IResolverContext context)
- {
- var product = (Product) context.ObjectValue;
- var reviews = Db.Reviews
- .Where(r => r.Value.Product.Upc == product.Upc)
- .Select(p => p.Value);
+ return ResolveSync.As(reviews);
+ }
- return ResolveSync.As(reviews);
- }
+ private static ValueTask ReviewAuthor(IResolverContext context)
+ {
+ var review = (Review)context.ObjectValue;
- private static ValueTask ReviewAuthor(IResolverContext context)
+ return ResolveSync.As(new User
{
- var review = (Review) context.ObjectValue;
+ ID = review.AuthorID,
+ Username = Db.Usernames[review.AuthorID]
+ });
+ }
- return ResolveSync.As(new User
- {
- ID = review.AuthorID,
- Username = Db.Usernames[review.AuthorID]
- });
- }
+ private static ValueTask UserReviews(IResolverContext context)
+ {
+ var user = (User)context.ObjectValue;
+ var reviews = Db.Reviews
+ .Where(r => r.Value.AuthorID == user.ID)
+ .Select(r => r.Value);
- private static ValueTask UserReviews(IResolverContext context)
- {
- var user = (User) context.ObjectValue;
- var reviews = Db.Reviews
- .Where(r => r.Value.AuthorID == user.ID)
- .Select(r => r.Value);
+ return ResolveSync.As(reviews);
+ }
- return ResolveSync.As(reviews);
- }
+ private static async ValueTask UserReference(
+ IResolverContext context,
+ TypeDefinition type,
+ IReadOnlyDictionary representation)
+ {
+ await Task.Delay(0);
- private static async ValueTask UserReference(
- IResolverContext context,
- INamedType type,
- IReadOnlyDictionary representation)
- {
- await Task.Delay(0);
+ if (!representation.TryGetValue("id", out var idObj))
+ throw new ArgumentOutOfRangeException("id", "Representation is missing the required 'id' value");
- if (!representation.TryGetValue("id", out var idObj))
- {
- throw new ArgumentOutOfRangeException("id", "Representation is missing the required 'id' value");
- }
+ var userId = idObj.ToString();
- var userId = idObj.ToString();
+ if (!Db.Usernames.TryGetValue(userId, out var username))
+ throw new ArgumentOutOfRangeException("id", $"User '{userId} not found");
- if (!Db.Usernames.TryGetValue(userId, out var username))
- {
- throw new ArgumentOutOfRangeException("id", $"User '{userId} not found");
- }
-
- var user = new User
- {
- ID = userId,
- Username = username
- };
+ var user = new User
+ {
+ ID = userId,
+ Username = username
+ };
- return new ResolveReferenceResult(type, user);
- }
+ return new ResolveReferenceResult(type, user);
}
+}
- public static class Db
+public static class Db
+{
+ public static Dictionary Reviews { get; } = new()
{
- public static Dictionary Reviews { get; } = new Dictionary
+ ["1"] = new Review
{
- ["1"] = new Review
- {
- ID = "1",
- AuthorID = "1",
- Product = new Product {Upc = "1"},
- Body = "Love it!"
- },
- ["2"] = new Review
- {
- ID = "2",
- AuthorID = "1",
- Product = new Product {Upc = "2"},
- Body = "Too expensive!"
- },
- ["3"] = new Review
- {
- ID = "3",
- AuthorID = "2",
- Product = new Product {Upc = "3"},
- Body = "Could be better"
- },
- ["4"] = new Review
- {
- ID = "4",
- AuthorID = "2",
- Product = new Product {Upc = "1"},
- Body = "Prefer something else"
- }
- };
-
- public static Dictionary Usernames { get; } = new Dictionary
+ ID = "1",
+ AuthorID = "1",
+ Product = new Product { Upc = "1" },
+ Body = "Love it!"
+ },
+ ["2"] = new Review
{
- ["1"] = "@ada",
- ["2"] = "@complete"
- };
- }
+ ID = "2",
+ AuthorID = "1",
+ Product = new Product { Upc = "2" },
+ Body = "Too expensive!"
+ },
+ ["3"] = new Review
+ {
+ ID = "3",
+ AuthorID = "2",
+ Product = new Product { Upc = "3" },
+ Body = "Could be better"
+ },
+ ["4"] = new Review
+ {
+ ID = "4",
+ AuthorID = "2",
+ Product = new Product { Upc = "1" },
+ Body = "Prefer something else"
+ }
+ };
- public class Review
+ public static Dictionary Usernames { get; } = new()
{
- public string ID { get; set; }
+ ["1"] = "@ada",
+ ["2"] = "@complete"
+ };
+}
- public string Body { get; set; }
+public class Review
+{
+ public string AuthorID { get; set; }
- public string AuthorID { get; set; }
+ public string Body { get; set; }
+ public string ID { get; set; }
- public Product Product { get; set; }
- }
+ public Product Product { get; set; }
+}
- public class User
- {
- public string ID { get; set; }
+public class User
+{
+ public string ID { get; set; }
- public string Username { get; set; }
- }
+ public string Username { get; set; }
+}
- public class Product
- {
- public string Upc { get; set; }
- }
+public class Product
+{
+ public string Upc { get; set; }
}
\ No newline at end of file
diff --git a/dev/GraphQL.Dev.Reviews/Startup.cs b/dev/GraphQL.Dev.Reviews/Startup.cs
index 71d7f719a..a4c971d71 100644
--- a/dev/GraphQL.Dev.Reviews/Startup.cs
+++ b/dev/GraphQL.Dev.Reviews/Startup.cs
@@ -6,45 +6,44 @@
using Tanka.GraphQL.Server;
using Tanka.GraphQL.Server.Links.DTOs;
-namespace GraphQL.Dev.Reviews
+namespace GraphQL.Dev.Reviews;
+
+public class Startup
{
- public class Startup
+ public Startup(IConfiguration configuration)
+ {
+ Configuration = configuration;
+ }
+
+ public IConfiguration Configuration { get; }
+
+ // This method gets called by the runtime. Use this method to add services to the container.
+ public void ConfigureServices(IServiceCollection services)
+ {
+ services.AddTankaGraphQL()
+ .ConfigureSchema(SchemaFactory.Create);
+
+ services.AddControllers()
+ .AddJsonOptions(options =>
+ {
+ // required to serialize
+ options.JsonSerializerOptions.Converters
+ .Add(new ObjectDictionaryConverter());
+ });
+ ;
+ }
+
+ // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
+ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
- public Startup(IConfiguration configuration)
- {
- Configuration = configuration;
- }
-
- public IConfiguration Configuration { get; }
-
- // This method gets called by the runtime. Use this method to add services to the container.
- public void ConfigureServices(IServiceCollection services)
- {
- services.AddTankaGraphQL()
- .ConfigureSchema(SchemaFactory.Create);
-
- services.AddControllers()
- .AddJsonOptions(options =>
- {
- // required to serialize
- options.JsonSerializerOptions.Converters
- .Add(new ObjectDictionaryConverter());
- });
- ;
- }
-
- // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
- public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
- {
- if (env.IsDevelopment()) app.UseDeveloperExceptionPage();
-
- app.UseHttpsRedirection();
-
- app.UseRouting();
-
- app.UseAuthorization();
-
- app.UseEndpoints(endpoints => { endpoints.MapControllers(); });
- }
+ if (env.IsDevelopment()) app.UseDeveloperExceptionPage();
+
+ app.UseHttpsRedirection();
+
+ app.UseRouting();
+
+ app.UseAuthorization();
+
+ app.UseEndpoints(endpoints => { endpoints.MapControllers(); });
}
}
\ No newline at end of file
diff --git a/dev/GraphQL.Dev.Reviews/appsettings.Development.json b/dev/GraphQL.Dev.Reviews/appsettings.Development.json
index 4f30a00f8..a73ce3176 100644
--- a/dev/GraphQL.Dev.Reviews/appsettings.Development.json
+++ b/dev/GraphQL.Dev.Reviews/appsettings.Development.json
@@ -6,4 +6,4 @@
"Microsoft.Hosting.Lifetime": "Information"
}
}
-}
+}
\ No newline at end of file
diff --git a/dev/GraphQL.Dev.Reviews/appsettings.json b/dev/GraphQL.Dev.Reviews/appsettings.json
index d9d9a9bff..222224e36 100644
--- a/dev/GraphQL.Dev.Reviews/appsettings.json
+++ b/dev/GraphQL.Dev.Reviews/appsettings.json
@@ -7,4 +7,4 @@
}
},
"AllowedHosts": "*"
-}
+}
\ No newline at end of file
diff --git a/dev/graphql.dev.allocations/Program.cs b/dev/graphql.dev.allocations/Program.cs
index 5210b4aa4..d537c5fde 100644
--- a/dev/graphql.dev.allocations/Program.cs
+++ b/dev/graphql.dev.allocations/Program.cs
@@ -3,19 +3,18 @@
using System.Linq;
using Tanka.GraphQL.Language;
-namespace Tanka.GraphQL.Dev.Allocations
+namespace Tanka.GraphQL.Dev.Allocations;
+
+public class Program
{
- public class Program
+ private static void Main(string[] args)
{
- private static void Main(string[] args)
- {
- var parser = Parser.Create(File.ReadAllBytes("RealWorldSchemas/github.graphql"));
- var typeSystem = parser.ParseTypeSystemDocument();
+ var parser = Parser.Create(File.ReadAllBytes("RealWorldSchemas/github.graphql"));
+ var typeSystem = parser.ParseTypeSystemDocument();
- if (typeSystem.TypeDefinitions == null || !typeSystem.TypeDefinitions.Any())
- throw new Exception("It has types");
+ if (typeSystem.TypeDefinitions == null || !typeSystem.TypeDefinitions.Any())
+ throw new Exception("It has types");
- Console.WriteLine("Parsed");
- }
+ Console.WriteLine("Parsed");
}
}
\ No newline at end of file
diff --git a/dev/graphql.dev.allocations/graphql.dev.allocations.csproj b/dev/graphql.dev.allocations/graphql.dev.allocations.csproj
index 531f56bc5..2b5f0d434 100644
--- a/dev/graphql.dev.allocations/graphql.dev.allocations.csproj
+++ b/dev/graphql.dev.allocations/graphql.dev.allocations.csproj
@@ -2,7 +2,7 @@
Exe
- net5.0
+ net6.0
false
tanka.graphql.dev.allocations
Tanka.GraphQL.Dev.Allocations
diff --git a/dev/graphql.dev.chat.data/ChatResolverService.cs b/dev/graphql.dev.chat.data/ChatResolverService.cs
index d3c9f0490..e403aca73 100644
--- a/dev/graphql.dev.chat.data/ChatResolverService.cs
+++ b/dev/graphql.dev.chat.data/ChatResolverService.cs
@@ -1,49 +1,48 @@
using System.Threading;
using System.Threading.Tasks;
-using Tanka.GraphQL.ValueResolution;
using Tanka.GraphQL.Samples.Chat.Data.Domain;
using Tanka.GraphQL.Server;
+using Tanka.GraphQL.ValueResolution;
+
+namespace Tanka.GraphQL.Samples.Chat.Data;
-namespace Tanka.GraphQL.Samples.Chat.Data
+public class ChatResolverService : IChatResolverService
{
- public class ChatResolverService : IChatResolverService
+ public async ValueTask GetMessagesAsync(IResolverContext context)
+ {
+ var messages = await context.Use().GetMessagesAsync(100);
+ return Resolve.As(messages);
+ }
+
+ public async ValueTask AddMessageAsync(IResolverContext context)
+ {
+ var input = context.GetObjectArgument("message");
+ var message = await context.Use().AddMessageAsync(
+ "1",
+ input.Content);
+
+ return Resolve.As(message);
+ }
+
+ public async ValueTask EditMessageAsync(IResolverContext context)
+ {
+ var id = context.GetArgument("id");
+ var input = context.GetObjectArgument("message");
+
+ var message = await context.Use().EditMessageAsync(
+ id,
+ input.Content);
+
+ return Resolve.As(message);
+ }
+
+ public ValueTask StreamMessagesAsync(IResolverContext context, CancellationToken unsubscribe)
+ {
+ return context.Use().JoinAsync(unsubscribe);
+ }
+
+ public ValueTask ResolveMessageAsync(IResolverContext context)
{
- public async ValueTask GetMessagesAsync(IResolverContext context)
- {
- var messages = await context.Use().GetMessagesAsync(100);
- return Resolve.As(messages);
- }
-
- public async ValueTask AddMessageAsync(IResolverContext context)
- {
- var input = context.GetObjectArgument("message");
- var message = await context.Use().AddMessageAsync(
- "1",
- input.Content);
-
- return Resolve.As(message);
- }
-
- public async ValueTask EditMessageAsync(IResolverContext context)
- {
- var id = context.GetArgument("id");
- var input = context.GetObjectArgument("message");
-
- var message = await context.Use().EditMessageAsync(
- id,
- input.Content);
-
- return Resolve.As(message);
- }
-
- public ValueTask StreamMessagesAsync(IResolverContext context, CancellationToken unsubscribe)
- {
- return context.Use().JoinAsync(unsubscribe);
- }
-
- public ValueTask ResolveMessageAsync(IResolverContext context)
- {
- return ResolveSync.As(context.ObjectValue);
- }
+ return ResolveSync.As(context.ObjectValue);
}
}
\ No newline at end of file
diff --git a/dev/graphql.dev.chat.data/ChatResolvers.cs b/dev/graphql.dev.chat.data/ChatResolvers.cs
index 0f9223dbf..ba992f16d 100644
--- a/dev/graphql.dev.chat.data/ChatResolvers.cs
+++ b/dev/graphql.dev.chat.data/ChatResolvers.cs
@@ -1,41 +1,40 @@
using Tanka.GraphQL.Samples.Chat.Data.Domain;
using static Tanka.GraphQL.ValueResolution.Resolve;
-namespace Tanka.GraphQL.Samples.Chat.Data
+namespace Tanka.GraphQL.Samples.Chat.Data;
+
+public class ChatResolvers : ResolversMap
{
- public class ChatResolvers : ObjectTypeMap
+ public ChatResolvers(IChatResolverService resolverService)
{
- public ChatResolvers(IChatResolverService resolverService)
+ this["Query"] = new FieldResolversMap
{
- this["Query"] = new FieldResolversMap
- {
- {"messages", resolverService.GetMessagesAsync}
- };
+ { "messages", resolverService.GetMessagesAsync }
+ };
- this["Mutation"] = new FieldResolversMap
- {
- {"addMessage", resolverService.AddMessageAsync},
- {"editMessage", resolverService.EditMessageAsync}
- };
+ this["Mutation"] = new FieldResolversMap
+ {
+ { "addMessage", resolverService.AddMessageAsync },
+ { "editMessage", resolverService.EditMessageAsync }
+ };
- this["Subscription"] = new FieldResolversMap
- {
- {"messages", resolverService.StreamMessagesAsync, resolverService.ResolveMessageAsync}
- };
+ this["Subscription"] = new FieldResolversMap
+ {
+ { "messages", resolverService.StreamMessagesAsync, resolverService.ResolveMessageAsync }
+ };
- this["Message"] = new FieldResolversMap
- {
- {"id", PropertyOf(m => m.Id)},
- {"from", PropertyOf(m => m.From)},
- {"content", PropertyOf(m => m.Content)},
- {"timestamp", PropertyOf(m => m.Timestamp)}
- };
+ this["Message"] = new FieldResolversMap
+ {
+ { "id", PropertyOf(m => m.Id) },
+ { "from", PropertyOf(m => m.From) },
+ { "content", PropertyOf(m => m.Content) },
+ { "timestamp", PropertyOf(m => m.Timestamp) }
+ };
- this["From"] = new FieldResolversMap
- {
- {"userId", PropertyOf(f => f.UserId)},
- {"name", PropertyOf(f => f.Name)}
- };
- }
+ this["From"] = new FieldResolversMap
+ {
+ { "userId", PropertyOf(f => f.UserId) },
+ { "name", PropertyOf(f => f.Name) }
+ };
}
}
\ No newline at end of file
diff --git a/dev/graphql.dev.chat.data/IChat.cs b/dev/graphql.dev.chat.data/IChat.cs
index 4dc35f88c..ed52574bb 100644
--- a/dev/graphql.dev.chat.data/IChat.cs
+++ b/dev/graphql.dev.chat.data/IChat.cs
@@ -4,88 +4,87 @@
using System.Threading;
using System.Threading.Tasks;
using Tanka.GraphQL.Channels;
-using Tanka.GraphQL.ValueResolution;
using Tanka.GraphQL.Samples.Chat.Data.Domain;
+using Tanka.GraphQL.ValueResolution;
+
+namespace Tanka.GraphQL.Samples.Chat.Data;
-namespace Tanka.GraphQL.Samples.Chat.Data
+public interface IChat
{
- public interface IChat
- {
- Task> GetMessagesAsync(
- int latest);
+ Task> GetMessagesAsync(
+ int latest);
- Task AddMessageAsync(
- string fromId,
- string content);
+ Task AddMessageAsync(
+ string fromId,
+ string content);
- Task EditMessageAsync(
- string id,
- string content);
+ Task EditMessageAsync(
+ string id,
+ string content);
- ValueTask JoinAsync(CancellationToken unsubscribe);
- }
+ ValueTask JoinAsync(CancellationToken unsubscribe);
+}
- public class Chat : IChat
+public class Chat : IChat
+{
+ private readonly Queue _messages = new();
+ private readonly EventChannel _messageStream;
+
+ private int _lastId;
+
+ public Chat()
{
- private readonly Queue _messages = new Queue();
- private readonly EventChannel _messageStream;
+ _messageStream = new EventChannel();
+ }
- private int _lastId;
+ public async Task> GetMessagesAsync(int latest)
+ {
+ await Task.Delay(0);
+ return _messages.Take(latest);
+ }
- public Chat()
+ public async Task AddMessageAsync(
+ string fromId,
+ string content)
+ {
+ var from = await GetFromAsync(fromId);
+ var message = new Message
{
- _messageStream = new EventChannel();
- }
+ Id = $"{++_lastId}",
+ Content = content,
+ Timestamp = DateTimeOffset.UtcNow,
+ From = from
+ };
- public async Task> GetMessagesAsync(int latest)
- {
- await Task.Delay(0);
- return _messages.Take(latest);
- }
+ _messages.Enqueue(message);
+ await _messageStream.WriteAsync(message);
+ return message;
+ }
- public async Task AddMessageAsync(
- string fromId,
- string content)
- {
- var from = await GetFromAsync(fromId);
- var message = new Message
- {
- Id = $"{++_lastId}",
- Content = content,
- Timestamp = DateTimeOffset.UtcNow,
- From = from
- };
-
- _messages.Enqueue(message);
- await _messageStream.WriteAsync(message);
- return message;
- }
-
- public async Task EditMessageAsync(string id, string content)
- {
- await Task.Delay(0);
- var originalMessage = _messages.SingleOrDefault(m => m.Id == id);
+ public async Task EditMessageAsync(string id, string content)
+ {
+ await Task.Delay(0);
+ var originalMessage = _messages.SingleOrDefault(m => m.Id == id);
- if (originalMessage == null)
- return null;
+ if (originalMessage == null)
+ return null;
- originalMessage.Content = content;
- return originalMessage;
- }
+ originalMessage.Content = content;
+ return originalMessage;
+ }
- public ValueTask JoinAsync(CancellationToken unsubscribe)
- {
- return new ValueTask(_messageStream.Subscribe(unsubscribe));
- }
+ public ValueTask JoinAsync(CancellationToken unsubscribe)
+ {
+ return new ValueTask(_messageStream.Subscribe(unsubscribe));
+ }
- private async Task GetFromAsync(string fromId)
+ private async Task GetFromAsync(string fromId)
+ {
+ await Task.Delay(0);
+ return new From
{
- await Task.Delay(0);
- return new From
- {
- UserId = fromId,
- Name = "From"
- };
- }
+ UserId = fromId,
+ Name = "From"
+ };
}
}
\ No newline at end of file
diff --git a/dev/graphql.dev.chat.data/IChatResolverService.cs b/dev/graphql.dev.chat.data/IChatResolverService.cs
index 8151b5baa..abdd126ad 100644
--- a/dev/graphql.dev.chat.data/IChatResolverService.cs
+++ b/dev/graphql.dev.chat.data/IChatResolverService.cs
@@ -2,18 +2,17 @@
using System.Threading.Tasks;
using Tanka.GraphQL.ValueResolution;
-namespace Tanka.GraphQL.Samples.Chat.Data
+namespace Tanka.GraphQL.Samples.Chat.Data;
+
+public interface IChatResolverService
{
- public interface IChatResolverService
- {
- ValueTask GetMessagesAsync(IResolverContext context);
+ ValueTask GetMessagesAsync(IResolverContext context);
- ValueTask AddMessageAsync(IResolverContext context);
+ ValueTask AddMessageAsync(IResolverContext context);
- ValueTask EditMessageAsync(IResolverContext context);
+ ValueTask EditMessageAsync(IResolverContext context);
- ValueTask StreamMessagesAsync(IResolverContext context, CancellationToken cancellationToken);
+ ValueTask StreamMessagesAsync(IResolverContext context, CancellationToken cancellationToken);
- ValueTask ResolveMessageAsync(IResolverContext context);
- }
+ ValueTask ResolveMessageAsync(IResolverContext context);
}
\ No newline at end of file
diff --git a/dev/graphql.dev.chat.data/domain/Schema.cs b/dev/graphql.dev.chat.data/domain/Schema.cs
index 76cf37970..e59284dd7 100644
--- a/dev/graphql.dev.chat.data/domain/Schema.cs
+++ b/dev/graphql.dev.chat.data/domain/Schema.cs
@@ -2,33 +2,30 @@
using System.Collections.Generic;
using Tanka.GraphQL.ValueResolution;
-namespace Tanka.GraphQL.Samples.Chat.Data.Domain
-{
- public class From
- {
- public string UserId { get; set; }
+namespace Tanka.GraphQL.Samples.Chat.Data.Domain;
- public string Name { get; set; }
- }
+public class From
+{
+ public string Name { get; set; }
+ public string UserId { get; set; }
+}
- public class Message
- {
- public string Id { get; set; }
+public class Message
+{
+ public string Content { get; set; }
- public From From { get; set; }
+ public From From { get; set; }
+ public string Id { get; set; }
- public string Content { get; set; }
+ public DateTimeOffset Timestamp { get; set; }
+}
- public DateTimeOffset Timestamp { get; set; }
- }
+public class InputMessage : IReadFromObjectDictionary
+{
+ public string Content { get; set; }
- public class InputMessage : IReadFromObjectDictionary
+ public void Read(IReadOnlyDictionary source)
{
- public string Content { get; set; }
-
- public void Read(IReadOnlyDictionary source)
- {
- Content = source.GetValue("content");
- }
+ Content = source.GetValue("content");
}
}
\ No newline at end of file
diff --git a/dev/graphql.dev.chat.data/graphql.dev.chat.data.csproj b/dev/graphql.dev.chat.data/graphql.dev.chat.data.csproj
index 39951e853..b9357351d 100644
--- a/dev/graphql.dev.chat.data/graphql.dev.chat.data.csproj
+++ b/dev/graphql.dev.chat.data/graphql.dev.chat.data.csproj
@@ -1,18 +1,14 @@
- net5.0
+ net6.0
Tanka.GraphQL.Samples.Chat.Data
Tanka.GraphQL.Samples.Chat.Data
false
-
-
-
-
-
+
-
+
diff --git a/dev/graphql.dev.chat.data/idl/IdlSchema.cs b/dev/graphql.dev.chat.data/idl/IdlSchema.cs
index efc794ca0..f35c008f4 100644
--- a/dev/graphql.dev.chat.data/idl/IdlSchema.cs
+++ b/dev/graphql.dev.chat.data/idl/IdlSchema.cs
@@ -2,34 +2,31 @@
using System.IO;
using System.Reflection;
using System.Text;
-using Tanka.GraphQL.SchemaBuilding;
-using Tanka.GraphQL.SDL;
-namespace Tanka.GraphQL.Samples.Chat.Data.IDL
+namespace Tanka.GraphQL.Samples.Chat.Data.IDL;
+
+public static class IdlSchema
{
- public static class IdlSchema
+ public static SchemaBuilder Load()
{
- public static SchemaBuilder Load()
- {
- var idl = LoadIdlFromResource();
- return new SchemaBuilder()
- .Sdl(idl);
- }
+ var idl = LoadIdlFromResource();
+ return new SchemaBuilder()
+ .Add(idl);
+ }
+
+ ///
+ /// Load schema from embedded resource
+ ///
+ ///
+ private static string LoadIdlFromResource()
+ {
+ var assembly = Assembly.GetExecutingAssembly();
+ var resourceStream =
+ assembly.GetManifestResourceStream("Tanka.GraphQL.Samples.Chat.Data.idl.schema.graphql");
+
+ using var reader =
+ new StreamReader(resourceStream ?? throw new InvalidOperationException(), Encoding.UTF8);
- ///
- /// Load schema from embedded resource
- ///
- ///
- private static string LoadIdlFromResource()
- {
- var assembly = Assembly.GetExecutingAssembly();
- var resourceStream =
- assembly.GetManifestResourceStream("Tanka.GraphQL.Samples.Chat.Data.IDL.schema.graphql");
-
- using var reader =
- new StreamReader(resourceStream ?? throw new InvalidOperationException(), Encoding.UTF8);
-
- return reader.ReadToEnd();
- }
+ return reader.ReadToEnd();
}
}
\ No newline at end of file
diff --git a/dev/graphql.dev.chat.web.3.1/.gitignore b/dev/graphql.dev.chat.web.3.1/.gitignore
deleted file mode 100644
index c72f0caa7..000000000
--- a/dev/graphql.dev.chat.web.3.1/.gitignore
+++ /dev/null
@@ -1,234 +0,0 @@
-/Properties/launchSettings.json
-
-## Ignore Visual Studio temporary files, build results, and
-## files generated by popular Visual Studio add-ons.
-
-# User-specific files
-*.suo
-*.user
-*.userosscache
-*.sln.docstates
-
-# User-specific files (MonoDevelop/Xamarin Studio)
-*.userprefs
-
-# Build results
-[Dd]ebug/
-[Dd]ebugPublic/
-[Rr]elease/
-[Rr]eleases/
-x64/
-x86/
-build/
-bld/
-bin/
-Bin/
-obj/
-Obj/
-
-# Visual Studio 2015 cache/options directory
-.vs/
-/wwwroot/dist/
-
-# MSTest test Results
-[Tt]est[Rr]esult*/
-[Bb]uild[Ll]og.*
-
-# NUNIT
-*.VisualState.xml
-TestResult.xml
-
-# Build Results of an ATL Project
-[Dd]ebugPS/
-[Rr]eleasePS/
-dlldata.c
-
-*_i.c
-*_p.c
-*_i.h
-*.ilk
-*.meta
-*.obj
-*.pch
-*.pdb
-*.pgc
-*.pgd
-*.rsp
-*.sbr
-*.tlb
-*.tli
-*.tlh
-*.tmp
-*.tmp_proj
-*.log
-*.vspscc
-*.vssscc
-.builds
-*.pidb
-*.svclog
-*.scc
-
-# Chutzpah Test files
-_Chutzpah*
-
-# Visual C++ cache files
-ipch/
-*.aps
-*.ncb
-*.opendb
-*.opensdf
-*.sdf
-*.cachefile
-
-# Visual Studio profiler
-*.psess
-*.vsp
-*.vspx
-*.sap
-
-# TFS 2012 Local Workspace
-$tf/
-
-# Guidance Automation Toolkit
-*.gpState
-
-# ReSharper is a .NET coding add-in
-_ReSharper*/
-*.[Rr]e[Ss]harper
-*.DotSettings.user
-
-# JustCode is a .NET coding add-in
-.JustCode
-
-# TeamCity is a build add-in
-_TeamCity*
-
-# DotCover is a Code Coverage Tool
-*.dotCover
-
-# NCrunch
-_NCrunch_*
-.*crunch*.local.xml
-nCrunchTemp_*
-
-# MightyMoose
-*.mm.*
-AutoTest.Net/
-
-# Web workbench (sass)
-.sass-cache/
-
-# Installshield output folder
-[Ee]xpress/
-
-# DocProject is a documentation generator add-in
-DocProject/buildhelp/
-DocProject/Help/*.HxT
-DocProject/Help/*.HxC
-DocProject/Help/*.hhc
-DocProject/Help/*.hhk
-DocProject/Help/*.hhp
-DocProject/Help/Html2
-DocProject/Help/html
-
-# Click-Once directory
-publish/
-
-# Publish Web Output
-*.[Pp]ublish.xml
-*.azurePubxml
-# TODO: Comment the next line if you want to checkin your web deploy settings
-# but database connection strings (with potential passwords) will be unencrypted
-*.pubxml
-*.publishproj
-
-# NuGet Packages
-*.nupkg
-# The packages folder can be ignored because of Package Restore
-**/packages/*
-# except build/, which is used as an MSBuild target.
-!**/packages/build/
-# Uncomment if necessary however generally it will be regenerated when needed
-#!**/packages/repositories.config
-
-# Microsoft Azure Build Output
-csx/
-*.build.csdef
-
-# Microsoft Azure Emulator
-ecf/
-rcf/
-
-# Microsoft Azure ApplicationInsights config file
-ApplicationInsights.config
-
-# Windows Store app package directory
-AppPackages/
-BundleArtifacts/
-
-# Visual Studio cache files
-# files ending in .cache can be ignored
-*.[Cc]ache
-# but keep track of directories ending in .cache
-!*.[Cc]ache/
-
-# Others
-ClientBin/
-~$*
-*~
-*.dbmdl
-*.dbproj.schemaview
-*.pfx
-*.publishsettings
-orleans.codegen.cs
-
-/node_modules
-
-# RIA/Silverlight projects
-Generated_Code/
-
-# Backup & report files from converting an old project file
-# to a newer Visual Studio version. Backup files are not needed,
-# because we have git ;-)
-_UpgradeReport_Files/
-Backup*/
-UpgradeLog*.XML
-UpgradeLog*.htm
-
-# SQL Server files
-*.mdf
-*.ldf
-
-# Business Intelligence projects
-*.rdl.data
-*.bim.layout
-*.bim_*.settings
-
-# Microsoft Fakes
-FakesAssemblies/
-
-# GhostDoc plugin setting file
-*.GhostDoc.xml
-
-# Node.js Tools for Visual Studio
-.ntvs_analysis.dat
-
-# Visual Studio 6 build log
-*.plg
-
-# Visual Studio 6 workspace options file
-*.opt
-
-# Visual Studio LightSwitch build output
-**/*.HTMLClient/GeneratedArtifacts
-**/*.DesktopClient/GeneratedArtifacts
-**/*.DesktopClient/ModelManifest.xml
-**/*.Server/GeneratedArtifacts
-**/*.Server/ModelManifest.xml
-_Pvt_Extensions
-
-# Paket dependency manager
-.paket/paket.exe
-
-# FAKE - F# Make
-.fake/
diff --git a/dev/graphql.dev.chat.web.3.1/Controllers/QueryController.cs b/dev/graphql.dev.chat.web.3.1/Controllers/QueryController.cs
deleted file mode 100644
index a00de062e..000000000
--- a/dev/graphql.dev.chat.web.3.1/Controllers/QueryController.cs
+++ /dev/null
@@ -1,34 +0,0 @@
-using System.Threading.Tasks;
-using Microsoft.AspNetCore.Mvc;
-using Tanka.GraphQL.Samples.Chat.Web.GraphQL;
-using Tanka.GraphQL.Server;
-using static Tanka.GraphQL.Parser;
-
-namespace Tanka.GraphQL.Samples.Chat.Web.Controllers
-{
- [Route("api/graphql")]
- public class QueryController : Controller
- {
- private readonly IQueryStreamService _queryStreamService;
-
- public QueryController(IQueryStreamService queryStreamService)
- {
- _queryStreamService = queryStreamService;
- }
-
- [HttpPost]
- public async Task Post([FromBody] OperationRequest request)
- {
- var stream = await _queryStreamService.QueryAsync(new Query
- {
- Document = ParseDocument(request.Query),
- Variables = request.Variables,
- OperationName = request.OperationName
- }, Request.HttpContext.RequestAborted);
-
- var result = await stream.Reader.ReadAsync();
-
- return Ok(result);
- }
- }
-}
\ No newline at end of file
diff --git a/dev/graphql.dev.chat.web.3.1/GraphQL/ChatSchemas.cs b/dev/graphql.dev.chat.web.3.1/GraphQL/ChatSchemas.cs
deleted file mode 100644
index c1451130c..000000000
--- a/dev/graphql.dev.chat.web.3.1/GraphQL/ChatSchemas.cs
+++ /dev/null
@@ -1,28 +0,0 @@
-using Tanka.GraphQL.Extensions.Analysis;
-using Tanka.GraphQL.Samples.Chat.Data;
-using Tanka.GraphQL.Samples.Chat.Data.IDL;
-using Tanka.GraphQL.Tools;
-using Tanka.GraphQL.TypeSystem;
-
-namespace Tanka.GraphQL.Samples.Chat.Web.GraphQL
-{
- public class ChatSchemas
- {
- public ChatSchemas(IChatResolverService resolverService)
- {
- var builder = IdlSchema.Load();
- var resolvers = new ChatResolvers(resolverService);
-
- // add cost directive support to schema
- builder.Include(CostAnalyzer.CostDirective);
-
- // build executable schema
- Chat = SchemaTools.MakeExecutableSchemaWithIntrospection(
- builder,
- resolvers,
- resolvers);
- }
-
- public ISchema Chat { get; set; }
- }
-}
\ No newline at end of file
diff --git a/dev/graphql.dev.chat.web.3.1/GraphQL/OperationRequest.cs b/dev/graphql.dev.chat.web.3.1/GraphQL/OperationRequest.cs
deleted file mode 100644
index 54b2b7c45..000000000
--- a/dev/graphql.dev.chat.web.3.1/GraphQL/OperationRequest.cs
+++ /dev/null
@@ -1,13 +0,0 @@
-using System.Collections.Generic;
-
-namespace Tanka.GraphQL.Samples.Chat.Web.GraphQL
-{
- public class OperationRequest
- {
- public string OperationName { get; set; }
-
- public string Query { get; set; }
-
- public Dictionary Variables { get; set; }
- }
-}
\ No newline at end of file
diff --git a/dev/graphql.dev.chat.web.3.1/Program.cs b/dev/graphql.dev.chat.web.3.1/Program.cs
deleted file mode 100644
index fe600e8af..000000000
--- a/dev/graphql.dev.chat.web.3.1/Program.cs
+++ /dev/null
@@ -1,17 +0,0 @@
-using Microsoft.AspNetCore;
-using Microsoft.AspNetCore.Hosting;
-
-namespace Tanka.GraphQL.Samples.Chat.Web
-{
- public class Program
- {
- public static void Main(string[] args)
- {
- CreateWebHostBuilder(args).Build().Run();
- }
-
- public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
- WebHost.CreateDefaultBuilder(args)
- .UseStartup();
- }
-}
diff --git a/dev/graphql.dev.chat.web.3.1/Startup.cs b/dev/graphql.dev.chat.web.3.1/Startup.cs
deleted file mode 100644
index b8e8337af..000000000
--- a/dev/graphql.dev.chat.web.3.1/Startup.cs
+++ /dev/null
@@ -1,115 +0,0 @@
-using System.Linq;
-using System.Text.Json;
-using System.Threading.Tasks;
-using GraphQL.Server.Ui.Playground;
-using Microsoft.AspNetCore.Builder;
-using Microsoft.AspNetCore.Hosting;
-using Microsoft.AspNetCore.Http.Connections;
-using Microsoft.AspNetCore.Mvc;
-using Microsoft.AspNetCore.WebSockets;
-using Microsoft.Extensions.Configuration;
-using Microsoft.Extensions.DependencyInjection;
-using Microsoft.Extensions.Hosting;
-using Tanka.GraphQL.Extensions.Analysis;
-using Tanka.GraphQL.Extensions.Tracing;
-using Tanka.GraphQL.Samples.Chat.Data;
-using Tanka.GraphQL.Samples.Chat.Web.GraphQL;
-using Tanka.GraphQL.Server;
-using Tanka.GraphQL.Server.Links.DTOs;
-using Tanka.GraphQL.TypeSystem;
-using Tanka.GraphQL.Validation;
-
-namespace Tanka.GraphQL.Samples.Chat.Web
-{
- public class Startup
- {
- public Startup(IConfiguration configuration)
- {
- Configuration = configuration;
- }
-
- public IConfiguration Configuration { get; }
-
- // This method gets called by the runtime. Use this method to add services to the container.
- public void ConfigureServices(IServiceCollection services)
- {
- services.AddControllers()
- .AddJsonOptions(options =>
- {
- // required to serialize
- options.JsonSerializerOptions.Converters
- .Add(new ObjectDictionaryConverter());
- options.JsonSerializerOptions.IgnoreNullValues = true;
- });
-
- // graphql
- services.AddSingleton();
- services.AddSingleton();
- services.AddSingleton();
- services.AddSingleton(provider => provider.GetRequiredService().Chat);
-
- // configure execution options
- services.AddTankaGraphQL()
- .ConfigureRules(rules => rules.Concat(new[]
- {
- CostAnalyzer.MaxCost(100, 1, true)
- }).ToArray())
- .ConfigureSchema(schema => new ValueTask(schema))
- .AddExtension()
- .ConfigureWebSockets();
-
-
- // signalr server
- services.AddSignalR(options => options.EnableDetailedErrors = true)
- .AddTankaGraphQL();
-
- // graphql-ws websocket server
- // web socket server
- services.AddWebSockets(options =>
- {
- options.AllowedOrigins.Add("https://localhost:5000");
- options.AllowedOrigins.Add("https://localhost:3000");
- });
-
- // CORS is required for the graphql.samples.chat.ui React App
- services.AddCors(options =>
- {
- options.AddDefaultPolicy(policy =>
- {
- policy.WithOrigins("http://localhost:3000");
- policy.AllowAnyHeader();
- policy.AllowAnyMethod();
- policy.AllowCredentials();
- policy.WithHeaders("X-Requested-With", "authorization");
- });
- });
- }
-
- public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
- {
- if (env.IsDevelopment())
- {
- app.UseDeveloperExceptionPage();
- }
- else
- {
- app.UseExceptionHandler("/Error");
- app.UseHsts();
- }
-
- app.UseCors();
- app.UseHttpsRedirection();
- app.UseStaticFiles();
- app.UseWebSockets();
-
- app.UseRouting();
- app.UseEndpoints(endpoints =>
- {
- endpoints.MapTankaGraphQLSignalR("/graphql");
- endpoints.MapTankaGraphQLWebSockets("/api/graphql");
-
- endpoints.MapControllers();
- });
- }
- }
-}
\ No newline at end of file
diff --git a/dev/graphql.dev.chat.web.3.1/appsettings.Development.json b/dev/graphql.dev.chat.web.3.1/appsettings.Development.json
deleted file mode 100644
index e203e9407..000000000
--- a/dev/graphql.dev.chat.web.3.1/appsettings.Development.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
- "Logging": {
- "LogLevel": {
- "Default": "Debug",
- "System": "Information",
- "Microsoft": "Information"
- }
- }
-}
diff --git a/dev/graphql.dev.chat.web.3.1/appsettings.json b/dev/graphql.dev.chat.web.3.1/appsettings.json
deleted file mode 100644
index f71f175a9..000000000
--- a/dev/graphql.dev.chat.web.3.1/appsettings.json
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "Logging": {
- "LogLevel": {
- "Default": "Debug"
- },
- "Console":
- {
- "IncludeScopes": true
- }
- },
- "AllowedHosts": "*"
-}
diff --git a/dev/graphql.dev.chat.web.3.1/graphql.dev.chat.web.3.1.csproj b/dev/graphql.dev.chat.web.3.1/graphql.dev.chat.web.3.1.csproj
deleted file mode 100644
index af56654d1..000000000
--- a/dev/graphql.dev.chat.web.3.1/graphql.dev.chat.web.3.1.csproj
+++ /dev/null
@@ -1,34 +0,0 @@
-
-
-
- netcoreapp3.1
- true
- Latest
- false
- Tanka.GraphQL.Samples.Chat.Web
- Tanka.GraphQL.Samples.Chat.Web
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/dev/graphql.dev.chat.web/Controllers/QueryController.cs b/dev/graphql.dev.chat.web/Controllers/QueryController.cs
index a00de062e..36cefbad2 100644
--- a/dev/graphql.dev.chat.web/Controllers/QueryController.cs
+++ b/dev/graphql.dev.chat.web/Controllers/QueryController.cs
@@ -2,33 +2,31 @@
using Microsoft.AspNetCore.Mvc;
using Tanka.GraphQL.Samples.Chat.Web.GraphQL;
using Tanka.GraphQL.Server;
-using static Tanka.GraphQL.Parser;
-namespace Tanka.GraphQL.Samples.Chat.Web.Controllers
+namespace Tanka.GraphQL.Samples.Chat.Web.Controllers;
+
+[Route("api/graphql")]
+public class QueryController : Controller
{
- [Route("api/graphql")]
- public class QueryController : Controller
- {
- private readonly IQueryStreamService _queryStreamService;
+ private readonly IQueryStreamService _queryStreamService;
- public QueryController(IQueryStreamService queryStreamService)
- {
- _queryStreamService = queryStreamService;
- }
+ public QueryController(IQueryStreamService queryStreamService)
+ {
+ _queryStreamService = queryStreamService;
+ }
- [HttpPost]
- public async Task Post([FromBody] OperationRequest request)
+ [HttpPost]
+ public async Task Post([FromBody] OperationRequest request)
+ {
+ var stream = await _queryStreamService.QueryAsync(new Query
{
- var stream = await _queryStreamService.QueryAsync(new Query
- {
- Document = ParseDocument(request.Query),
- Variables = request.Variables,
- OperationName = request.OperationName
- }, Request.HttpContext.RequestAborted);
+ Document = request.Query,
+ Variables = request.Variables,
+ OperationName = request.OperationName
+ }, Request.HttpContext.RequestAborted);
- var result = await stream.Reader.ReadAsync();
+ var result = await stream.Reader.ReadAsync();
- return Ok(result);
- }
+ return Ok(result);
}
}
\ No newline at end of file
diff --git a/dev/graphql.dev.chat.web/GraphQL/ChatSchemas.cs b/dev/graphql.dev.chat.web/GraphQL/ChatSchemas.cs
index c1451130c..6a3b75984 100644
--- a/dev/graphql.dev.chat.web/GraphQL/ChatSchemas.cs
+++ b/dev/graphql.dev.chat.web/GraphQL/ChatSchemas.cs
@@ -1,28 +1,23 @@
using Tanka.GraphQL.Extensions.Analysis;
using Tanka.GraphQL.Samples.Chat.Data;
using Tanka.GraphQL.Samples.Chat.Data.IDL;
-using Tanka.GraphQL.Tools;
using Tanka.GraphQL.TypeSystem;
-namespace Tanka.GraphQL.Samples.Chat.Web.GraphQL
+namespace Tanka.GraphQL.Samples.Chat.Web.GraphQL;
+
+public class ChatSchemas
{
- public class ChatSchemas
+ public ChatSchemas(IChatResolverService resolverService)
{
- public ChatSchemas(IChatResolverService resolverService)
- {
- var builder = IdlSchema.Load();
- var resolvers = new ChatResolvers(resolverService);
-
- // add cost directive support to schema
- builder.Include(CostAnalyzer.CostDirective);
+ var builder = IdlSchema.Load();
+ var resolvers = new ChatResolvers(resolverService);
- // build executable schema
- Chat = SchemaTools.MakeExecutableSchemaWithIntrospection(
- builder,
- resolvers,
- resolvers);
- }
+ // add cost directive support to schema
+ builder.Add(CostAnalyzer.CostDirective);
- public ISchema Chat { get; set; }
+ // build executable schema
+ Chat = builder.Build(resolvers, resolvers).Result;
}
+
+ public ISchema Chat { get; set; }
}
\ No newline at end of file
diff --git a/dev/graphql.dev.chat.web/GraphQL/OperationRequest.cs b/dev/graphql.dev.chat.web/GraphQL/OperationRequest.cs
index 54b2b7c45..7f988b84d 100644
--- a/dev/graphql.dev.chat.web/GraphQL/OperationRequest.cs
+++ b/dev/graphql.dev.chat.web/GraphQL/OperationRequest.cs
@@ -1,13 +1,12 @@
using System.Collections.Generic;
-namespace Tanka.GraphQL.Samples.Chat.Web.GraphQL
+namespace Tanka.GraphQL.Samples.Chat.Web.GraphQL;
+
+public class OperationRequest
{
- public class OperationRequest
- {
- public string OperationName { get; set; }
+ public string OperationName { get; set; }
- public string Query { get; set; }
+ public string Query { get; set; }
- public Dictionary Variables { get; set; }
- }
+ public Dictionary Variables { get; set; }
}
\ No newline at end of file
diff --git a/dev/graphql.dev.chat.web/Program.cs b/dev/graphql.dev.chat.web/Program.cs
index fe600e8af..6ff53c6bf 100644
--- a/dev/graphql.dev.chat.web/Program.cs
+++ b/dev/graphql.dev.chat.web/Program.cs
@@ -1,17 +1,18 @@
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
-namespace Tanka.GraphQL.Samples.Chat.Web
+namespace Tanka.GraphQL.Samples.Chat.Web;
+
+public class Program
{
- public class Program
+ public static void Main(string[] args)
{
- public static void Main(string[] args)
- {
- CreateWebHostBuilder(args).Build().Run();
- }
+ CreateWebHostBuilder(args).Build().Run();
+ }
- public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
- WebHost.CreateDefaultBuilder(args)
- .UseStartup();
+ public static IWebHostBuilder CreateWebHostBuilder(string[] args)
+ {
+ return WebHost.CreateDefaultBuilder(args)
+ .UseStartup();
}
-}
+}
\ No newline at end of file
diff --git a/dev/graphql.dev.chat.web/Startup.cs b/dev/graphql.dev.chat.web/Startup.cs
index 431e7673c..1f9502b03 100644
--- a/dev/graphql.dev.chat.web/Startup.cs
+++ b/dev/graphql.dev.chat.web/Startup.cs
@@ -1,11 +1,7 @@
using System.Linq;
-using System.Text.Json;
using System.Threading.Tasks;
-using GraphQL.Server.Ui.Playground;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
-using Microsoft.AspNetCore.Http.Connections;
-using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.WebSockets;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
@@ -18,102 +14,98 @@
using Tanka.GraphQL.Server.Links.DTOs;
using Tanka.GraphQL.TypeSystem;
-namespace Tanka.GraphQL.Samples.Chat.Web
+namespace Tanka.GraphQL.Samples.Chat.Web;
+
+public class Startup
{
- public class Startup
+ public Startup(IConfiguration configuration, IWebHostEnvironment env)
{
- public Startup(IConfiguration configuration, IWebHostEnvironment env)
- {
- Configuration = configuration;
- Env = env;
- }
-
- public IConfiguration Configuration { get; }
- public IWebHostEnvironment Env { get; }
+ Configuration = configuration;
+ Env = env;
+ }
- // This method gets called by the runtime. Use this method to add services to the container.
- public void ConfigureServices(IServiceCollection services)
- {
- services.AddControllers()
- .AddJsonOptions(options =>
- {
- // required to serialize
- options.JsonSerializerOptions.Converters
- .Add(new ObjectDictionaryConverter());
- options.JsonSerializerOptions.IgnoreNullValues = true;
- });
+ public IConfiguration Configuration { get; }
+ public IWebHostEnvironment Env { get; }
- // graphql
- services.AddSingleton();
- services.AddSingleton();
- services.AddSingleton();
- services.AddSingleton(provider => provider.GetRequiredService().Chat);
+ // This method gets called by the runtime. Use this method to add services to the container.
+ public void ConfigureServices(IServiceCollection services)
+ {
+ services.AddControllers()
+ .AddJsonOptions(options =>
+ {
+ // required to serialize
+ options.JsonSerializerOptions.Converters
+ .Add(new ObjectDictionaryConverter());
+ options.JsonSerializerOptions.IgnoreNullValues = true;
+ });
- // configure execution options
- var tanka = services.AddTankaGraphQL()
- .ConfigureRules(rules => rules.Concat(new[]
- {
- CostAnalyzer.MaxCost(100, 1, true)
- }).ToArray())
- .ConfigureSchema(schema => new ValueTask(schema))
- .ConfigureWebSockets();
+ // graphql
+ services.AddSingleton();
+ services.AddSingleton();
+ services.AddSingleton();
+ services.AddSingleton(provider => provider.GetRequiredService().Chat);
- if (Env.IsDevelopment())
+ // configure execution options
+ var tanka = services.AddTankaGraphQL()
+ .ConfigureRules(rules => rules.Concat(new[]
{
- tanka.AddExtension();
- }
+ CostAnalyzer.MaxCost(100, 1, true)
+ }).ToArray())
+ .ConfigureSchema(schema => new ValueTask(schema))
+ .ConfigureWebSockets();
- // signalr server
- services.AddSignalR(options => options.EnableDetailedErrors = true)
- .AddTankaGraphQL();
+ if (Env.IsDevelopment()) tanka.AddExtension();
- // graphql-ws websocket server
- // web socket server
- services.AddWebSockets(options =>
- {
- options.AllowedOrigins.Add("https://localhost:5000");
- options.AllowedOrigins.Add("https://localhost:3000");
- });
+ // signalr server
+ services.AddSignalR(options => options.EnableDetailedErrors = true)
+ .AddTankaGraphQL();
+
+ // graphql-ws websocket server
+ // web socket server
+ services.AddWebSockets(options =>
+ {
+ options.AllowedOrigins.Add("https://localhost:5000");
+ options.AllowedOrigins.Add("https://localhost:3000");
+ });
- // CORS is required for the graphql.samples.chat.ui React App
- services.AddCors(options =>
+ // CORS is required for the graphql.samples.chat.ui React App
+ services.AddCors(options =>
+ {
+ options.AddDefaultPolicy(policy =>
{
- options.AddDefaultPolicy(policy =>
- {
- policy.WithOrigins("http://localhost:3000");
- policy.AllowAnyHeader();
- policy.AllowAnyMethod();
- policy.AllowCredentials();
- //policy.WithHeaders("X-Requested-With", "authorization");
- });
+ policy.WithOrigins("http://localhost:3000");
+ policy.AllowAnyHeader();
+ policy.AllowAnyMethod();
+ policy.AllowCredentials();
+ //policy.WithHeaders("X-Requested-With", "authorization");
});
- }
+ });
+ }
- public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
+ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
+ {
+ if (env.IsDevelopment())
{
- if (env.IsDevelopment())
- {
- app.UseDeveloperExceptionPage();
- }
- else
- {
- app.UseExceptionHandler("/Error");
- app.UseHsts();
- }
+ app.UseDeveloperExceptionPage();
+ }
+ else
+ {
+ app.UseExceptionHandler("/Error");
+ app.UseHsts();
+ }
- app.UseCors();
- app.UseHttpsRedirection();
- app.UseStaticFiles();
- app.UseWebSockets();
+ app.UseCors();
+ app.UseHttpsRedirection();
+ app.UseStaticFiles();
+ app.UseWebSockets();
- app.UseRouting();
- app.UseEndpoints(endpoints =>
- {
- endpoints.MapTankaGraphQLSignalR("/graphql");
- endpoints.MapTankaGraphQLWebSockets("/api/graphql");
+ app.UseRouting();
+ app.UseEndpoints(endpoints =>
+ {
+ endpoints.MapTankaGraphQLSignalR("/graphql");
+ endpoints.MapTankaGraphQLWebSockets("/api/graphql");
- endpoints.MapControllers();
- });
- }
+ endpoints.MapControllers();
+ });
}
}
\ No newline at end of file
diff --git a/dev/graphql.dev.chat.web/appsettings.Development.json b/dev/graphql.dev.chat.web/appsettings.Development.json
index e203e9407..f999bc20e 100644
--- a/dev/graphql.dev.chat.web/appsettings.Development.json
+++ b/dev/graphql.dev.chat.web/appsettings.Development.json
@@ -6,4 +6,4 @@
"Microsoft": "Information"
}
}
-}
+}
\ No newline at end of file
diff --git a/dev/graphql.dev.chat.web/appsettings.json b/dev/graphql.dev.chat.web/appsettings.json
index f71f175a9..5cc9dce57 100644
--- a/dev/graphql.dev.chat.web/appsettings.json
+++ b/dev/graphql.dev.chat.web/appsettings.json
@@ -9,4 +9,4 @@
}
},
"AllowedHosts": "*"
-}
+}
\ No newline at end of file
diff --git a/dev/graphql.dev.chat.web/graphql.dev.chat.web.csproj b/dev/graphql.dev.chat.web/graphql.dev.chat.web.csproj
index fed25264b..d5924828b 100644
--- a/dev/graphql.dev.chat.web/graphql.dev.chat.web.csproj
+++ b/dev/graphql.dev.chat.web/graphql.dev.chat.web.csproj
@@ -1,7 +1,7 @@
- net5.0
+ net6.0
true
Latest
false
@@ -21,7 +21,7 @@
-
+
diff --git a/global.json b/global.json
index 2c63c0851..7a73a41bf 100644
--- a/global.json
+++ b/global.json
@@ -1,2 +1,2 @@
{
-}
+}
\ No newline at end of file
diff --git a/run-benchmarks.ps1 b/run-benchmarks.ps1
index 7ed687ad0..26ad06230 100644
--- a/run-benchmarks.ps1
+++ b/run-benchmarks.ps1
@@ -50,7 +50,7 @@ $IsPreRelease = $PreReleaseTag -ne ''
"----------------------------------------"
"Benchmarks"
-$BechmarkCmd = "dotnet run --project ./benchmarks/graphql.benchmarks/graphql.benchmarks.csproj -c Release --framework net5.0 -- -i -m --filter *execution*"
+$BechmarkCmd = "dotnet run --project ./benchmarks/graphql.benchmarks/graphql.benchmarks.csproj -c Release --framework net6.0 -- -i -m --filter *execution*"
if ($IsPreRelease) {
$BechmarkCmd += " --job short"
diff --git a/src/GraphQL.Extensions.ApolloFederation/AnyScalarConverter.cs b/src/GraphQL.Extensions.ApolloFederation/AnyScalarConverter.cs
index 45a8c92ac..583c3163f 100644
--- a/src/GraphQL.Extensions.ApolloFederation/AnyScalarConverter.cs
+++ b/src/GraphQL.Extensions.ApolloFederation/AnyScalarConverter.cs
@@ -1,28 +1,27 @@
using Tanka.GraphQL.Language.Nodes;
using Tanka.GraphQL.TypeSystem.ValueSerialization;
-namespace Tanka.GraphQL.Extensions.ApolloFederation
+namespace Tanka.GraphQL.Extensions.ApolloFederation;
+
+public class AnyScalarConverter : IValueConverter
{
- public class AnyScalarConverter : IValueConverter
+ public object? Serialize(object value)
{
- public object? Serialize(object value)
- {
- return value;
- }
+ return value;
+ }
- public ValueBase SerializeLiteral(object? value)
- {
- return new NullValue();
- }
+ public ValueBase SerializeLiteral(object? value)
+ {
+ return new NullValue();
+ }
- public object? ParseValue(object input)
- {
- return input;
- }
+ public object? ParseValue(object input)
+ {
+ return input;
+ }
- public object? ParseLiteral(ValueBase input)
- {
- return input;
- }
+ public object? ParseLiteral(ValueBase input)
+ {
+ return input;
}
}
\ No newline at end of file
diff --git a/src/GraphQL.Extensions.ApolloFederation/DictionaryReferenceResolversMap.cs b/src/GraphQL.Extensions.ApolloFederation/DictionaryReferenceResolversMap.cs
index dc12c5a96..af1c95b92 100644
--- a/src/GraphQL.Extensions.ApolloFederation/DictionaryReferenceResolversMap.cs
+++ b/src/GraphQL.Extensions.ApolloFederation/DictionaryReferenceResolversMap.cs
@@ -1,12 +1,11 @@
using System.Collections.Generic;
-namespace Tanka.GraphQL.Extensions.ApolloFederation
+namespace Tanka.GraphQL.Extensions.ApolloFederation;
+
+public class DictionaryReferenceResolversMap : Dictionary, IReferenceResolversMap
{
- public class DictionaryReferenceResolversMap : Dictionary, IReferenceResolversMap
+ public bool TryGetReferenceResolver(string type, out ResolveReference resolveReference)
{
- public bool TryGetReferenceResolver(string type, out ResolveReference resolveReference)
- {
- return TryGetValue(type, out resolveReference);
- }
+ return TryGetValue(type, out resolveReference);
}
}
\ No newline at end of file
diff --git a/src/GraphQL.Extensions.ApolloFederation/Federation.cs b/src/GraphQL.Extensions.ApolloFederation/Federation.cs
index 735469c8b..7692452b1 100644
--- a/src/GraphQL.Extensions.ApolloFederation/Federation.cs
+++ b/src/GraphQL.Extensions.ApolloFederation/Federation.cs
@@ -1,184 +1,221 @@
using System.Collections.Generic;
using System.Linq;
+using System.Threading.Tasks;
using Tanka.GraphQL.Language;
-using Tanka.GraphQL.SchemaBuilding;
-using Tanka.GraphQL.SDL;
+using Tanka.GraphQL.Language.Nodes;
+using Tanka.GraphQL.Language.Nodes.TypeSystem;
using Tanka.GraphQL.TypeSystem;
+using Tanka.GraphQL.TypeSystem.ValueSerialization;
using Tanka.GraphQL.ValueResolution;
-namespace Tanka.GraphQL.Extensions.ApolloFederation
+namespace Tanka.GraphQL.Extensions.ApolloFederation;
+
+public record FederatedSchemaBuildOptions
+{
+ public IReferenceResolversMap? ReferenceResolvers { get; init; }
+ public SchemaBuildOptions? SchemaBuildOptions { get; init; }
+}
+
+public static class Federation
{
- public static class Federation
+ private static readonly IReadOnlyList IgnoredTypeNames = new List
{
- private static readonly IReadOnlyList IgnoredTypeNames = new List
- {
- "external",
- "requires",
- "provides",
- "key",
- "extends",
- "_Service",
- "_Entity",
- "_Any",
- "_FieldSet"
- };
+ "external",
+ "requires",
+ "provides",
+ "key",
+ "extends",
+ "_Service",
+ "_Entity",
+ "_Any",
+ "_FieldSet"
+ };
+
+ private static IReadOnlyDictionary NoConverters { get; } =
+ new Dictionary(0);
+
+ private static object Service { get; } = new();
+
+ public static Task BuildSubgraph(this SchemaBuilder builder, FederatedSchemaBuildOptions options)
+ {
+ var schemaBuildOptions = options.SchemaBuildOptions ?? new SchemaBuildOptions();
- public static SchemaBuilder ServiceFrom(
- ISchema schema,
- IReferenceResolversMap referenceResolvers)
+ // query types entity types from builder (note that anything added after this wont' show up
+ var entities = builder.QueryTypeDefinitions(type => type.HasDirective("key"), new SchemaBuildOptions
{
- var builder = new SchemaBuilder()
- .Import(schema);
+ BuildTypesFromOrphanedExtensions = true
+ }).ToList();
- builder.Union("_Entity", out var entityUnion, possibleTypes: GetEntities(builder));
- builder.Object("_Service", out var serviceObject);
+ // add federation types
+ builder.Add(FederationTypes.TypeSystem);
- if (!builder.TryGetQuery(out var queryObject))
- builder.Query(out queryObject);
+ var resolvers = new ResolversMap(
+ schemaBuildOptions.Resolvers ?? ResolversMap.None,
+ schemaBuildOptions.Subscribers);
- var entitiesResolver = CreateEntitiesResolver(referenceResolvers);
- builder.Connections(connect =>
+ // If no types are annotated with the key directive,
+ // then the _Entity union and Query._entities field should be removed from the schema.
+ if (entities.Any())
+ {
+ builder.Add(new TypeExtension(
+ new UnionDefinition(
+ null,
+ "_Entity",
+ null,
+ new UnionMemberTypes(entities.Select(e => new NamedType(e.Name)).ToList()))
+ ));
+
+ builder.Add(new TypeExtension(
+ new ObjectDefinition(null,
+ "Query",
+ fields: new FieldsDefinition(
+ new FieldDefinition[]
+ {
+ "_entities(representations: [_Any!]!): [_Entity]!",
+ "_service: _Service!"
+ }))));
+
+ resolvers += new ResolversMap
{
- connect.Field(
- queryObject,
- "_entities",
- new NonNull(new List(entityUnion)),
- args: args =>
- {
- args.Arg(
- "representations",
- new NonNull(new List(new NonNull(FederationTypes._Any))),
- null,
- "Representations");
- },
- resolve: resolve => resolve.Run(entitiesResolver));
-
- connect.Field(
- queryObject,
- "_service",
- new NonNull(serviceObject),
- "Federation",
- resolve => resolve.Run(context => ResolveSync.As(new object())));
-
- connect.Field(
- serviceObject,
- "sdl",
- ScalarType.NonNullString,
- "SDL",
- resolve => resolve.Run(CreateSdlResolver()));
- });
-
- return builder;
- }
+ { "Query", "_service", _ => ResolveSync.As(Service) },
+ {
+ "Query", "_entities",
+ CreateEntitiesResolver(options.ReferenceResolvers ?? new DictionaryReferenceResolversMap())
+ },
- private static ObjectType[] GetEntities(SchemaBuilder builder)
- {
- return builder.GetTypes()
- .Where(obj => obj.HasDirective("key"))
- .ToArray();
+ { "_Service", "sdl", CreateSdlResolver() }
+ };
}
- private static Resolver CreateSdlResolver()
+
+ schemaBuildOptions = schemaBuildOptions with
{
- return context =>
+ ValueConverters =
+ new Dictionary(schemaBuildOptions.ValueConverters ?? NoConverters)
{
- var options = new SchemaPrinterOptions(context.ExecutionContext.Schema);
- var defaultShouldPrintType = options.ShouldPrintType;
- options.ShouldPrintType = type =>
- {
- if (type is DirectiveType directiveType)
- if (IgnoredTypeNames.Contains(directiveType.Name))
- return false;
+ { "_Any", new AnyScalarConverter() },
+ { "_FieldSet", new FieldSetScalarConverter() }
+ },
+ Resolvers = resolvers,
+ Subscribers = resolvers,
+ BuildTypesFromOrphanedExtensions = true
+ };
- if (type is INamedType namedType)
- if (IgnoredTypeNames.Contains(namedType.Name))
- return false;
+ return builder.Build(schemaBuildOptions);
+ }
- if (type is ComplexType complexType)
- {
- var fields = context.ExecutionContext.Schema
- .GetFields(complexType.Name);
+ private static IReadOnlyList GetEntities(ISchema schema)
+ {
+ return schema.QueryTypes()
+ .Where(obj => obj.HasDirective("key"))
+ .Select(entity => new NamedType(entity.Name, null))
+ .ToList();
+ }
- if (!fields.Any())
- return false;
- }
+ private static Resolver CreateSdlResolver()
+ {
+ return context =>
+ {
+ /*var options = new SchemaPrinterOptions(context.ExecutionContext.Schema);
+ var defaultShouldPrintType = options.ShouldPrintType;
+ options.ShouldPrintType = type =>
+ {
+ if (type is DirectiveType directiveType)
+ if (IgnoredTypeNames.Contains(directiveType.Name))
+ return false;
- return defaultShouldPrintType(type);
- };
+ if (type is INamedType namedType)
+ if (IgnoredTypeNames.Contains(namedType.Name))
+ return false;
- var defaultShouldPrintField = options.ShouldPrintField;
- options.ShouldPrintField = (name, field) =>
+ if (type is ComplexType complexType)
{
- if (name == "_service")
- return false;
+ var fields = context.ExecutionContext.Schema
+ .GetFields(complexType.Name);
- if (name == "_entities")
+ if (!fields.Any())
return false;
+ }
- return defaultShouldPrintField(name, field);
- };
-
- var document = SchemaPrinter.Print(options);
- var sdl = Printer.Print(document);
- return ResolveSync.As(sdl);
+ return defaultShouldPrintType(type);
};
- }
- private static Resolver CreateEntitiesResolver(
- IReferenceResolversMap referenceResolversMap)
- {
- return async context =>
+ var defaultShouldPrintField = options.ShouldPrintField;
+ options.ShouldPrintField = (name, field) =>
{
- var representations = context
- .GetArgument>("representations");
+ if (name == "_service")
+ return false;
- var result = new List