Repository: JosephWoodward/graphiql-dotnet
Branch: master
Commit: 183de6e51968
Files: 38
Total size: 84.6 KB
Directory structure:
gitextract_vo8n6p94/
├── .github/
│ └── workflows/
│ └── dotnetcore.yml
├── .gitignore
├── GraphiQl.sln
├── LICENSE
├── README.md
├── assets/
│ └── logo.psd
├── package.sh
├── src/
│ └── GraphiQl/
│ ├── AssetProvider.cs
│ ├── GraphiQl.csproj
│ ├── GraphiQlExtensions.cs
│ ├── GraphiQlMiddleware.cs
│ ├── GraphiQlOptions.cs
│ └── assets/
│ ├── graphiql.css
│ └── index.html
└── tests/
├── GraphiQl.Demo/
│ ├── .bowerrc
│ ├── Controllers/
│ │ └── GraphQlController.cs
│ ├── GraphQl/
│ │ ├── Droid.cs
│ │ ├── GraphQlQuery.cs
│ │ └── Models/
│ │ ├── DroidType.cs
│ │ └── StarWarsQuery.cs
│ ├── GraphiQl.Demo.csproj
│ ├── Program.cs
│ ├── Properties/
│ │ └── launchSettings.json
│ ├── Startup.cs
│ ├── appsettings.Development.json
│ └── appsettings.json
└── GraphiQl.Tests/
├── AuthenticationTest/
│ ├── ConfigureOptionsSetup.cs
│ └── DelegateSetup.cs
├── BasicTest.cs
├── Fixtures/
│ ├── GraphQlFixture.cs
│ └── HostFixture.cs
├── GraphiQl.Tests.csproj
├── OverrideGraphQlPathTests/
│ ├── ConfigureOptionsSetup.cs
│ └── DelegateSetup.cs
├── OverrideGraphiQlPathTests/
│ ├── ConfigureOptionsSetup.cs
│ └── DelegateSetup.cs
├── SeleniumTest.cs
└── xunit.runner.json
================================================
FILE CONTENTS
================================================
================================================
FILE: .github/workflows/dotnetcore.yml
================================================
name: .NET Core
on: [push, pull_request]
jobs:
build:
name: Github Actions Build
# runs-on: ubuntu-latest
runs-on: windows-latest
steps:
- uses: actions/checkout@v1
- name: Setup .NET Core
uses: actions/setup-dotnet@v1
with:
dotnet-version: 3.1.100
- name: Build Reason
run: echo ${{github.ref}} and ${{github.event_name}}
- name: Build with dotnet
run: dotnet build --configuration Release --nologo
- name: Run tests
run: dotnet test tests/GraphiQl.Tests/ --configuration Release --nologo
# - if: github.event_name == 'push' && (github.ref == 'refs/heads/master' || contains(github.ref, 'tags'))
# name: Push CI
# run: ./push.sh ${{ secrets.FEEDZ_KEY }}
env:
DOTNET_CLI_TELEMETRY_OPTOUT: 1
================================================
FILE: .gitignore
================================================
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
# User-specific files
*.suo
*.user
*.sln.docstates
.vs
.vscode
.idea
# Build results
[Dd]ebug/
[Rr]elease/
x64/
build/
package/
[Bb]in/
[Oo]bj/
#dist/
# Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets
!packages/*/build/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
*_i.c
*_p.c
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.log
*.scc
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opensdf
*.sdf
*.cachefile
# Visual Studio profiler
*.psess
*.vsp
*.vspx
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# NCrunch
*.ncrunch*
.*crunch*.local.xml
# 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
*.Publish.xml
# NuGet Packages Directory
packages/
!packages/repositories.config
# Windows Azure Build Output
csx
*.build.csdef
# Windows Store app package directory
AppPackages/
# Others
sql/
*.Cache
ClientBin/
[Ss]tyle[Cc]op.*
~$*
*~
*.dbmdl
*.[Pp]ublish.xml
*.pfx
*.publishsettings
node_modules/
bower_components/
tmp/
# 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
App_Data/*.mdf
App_Data/*.ldf
#LightSwitch generated files
GeneratedArtifacts/
_Pvt_Extensions/
ModelManifest.xml
# =========================
# Windows detritus
# =========================
# Windows image file caches
Thumbs.db
ehthumbs.db
# Folder config file
Desktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Mac desktop service store files
.DS_Store
bower_components/
node_modules/
**/wwwroot/lib/
**/wwwroot/img/media/
.settings
**/PublishProfiles/
**/PublishScripts/
# Angular 2
# compiled output
AdminApp/dist
AdminApp/tmp
# dependencies
AdminApp/node_modules
AdminApp/bower_components
# IDEs and editors
AdminApp/.idea
# misc
AdminApp/.sass-cache
AdminApp/connect.lock
AdminApp/coverage/*
AdminApp/libpeerconnection.log
AdminApp/AdminApp/npm-debug.log
AdminApp/testem.log
AdminApp/typings
# e2e
AdminApp/e2e/*.js
AdminApp/e2e/*.map
#System Files
.DS_Store
Thumbs.db
================================================
FILE: GraphiQl.sln
================================================
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26124.0
MinimumVisualStudioVersion = 15.0.26124.0
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GraphiQl", "src\GraphiQl\GraphiQl.csproj", "{7DECE8E2-141A-4A14-A460-A7985C3AA2E8}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GraphiQl.Tests", "tests\GraphiQl.Tests\GraphiQl.Tests.csproj", "{0C2E2EB0-8FA2-4AB9-8642-72E50A830DBA}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GraphiQl.Demo", "tests\GraphiQl.Demo\GraphiQl.Demo.csproj", "{6482AE1A-896B-45A4-93D2-1DEA62120365}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{7DECE8E2-141A-4A14-A460-A7985C3AA2E8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7DECE8E2-141A-4A14-A460-A7985C3AA2E8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7DECE8E2-141A-4A14-A460-A7985C3AA2E8}.Debug|x64.ActiveCfg = Debug|Any CPU
{7DECE8E2-141A-4A14-A460-A7985C3AA2E8}.Debug|x64.Build.0 = Debug|Any CPU
{7DECE8E2-141A-4A14-A460-A7985C3AA2E8}.Debug|x86.ActiveCfg = Debug|Any CPU
{7DECE8E2-141A-4A14-A460-A7985C3AA2E8}.Debug|x86.Build.0 = Debug|Any CPU
{7DECE8E2-141A-4A14-A460-A7985C3AA2E8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7DECE8E2-141A-4A14-A460-A7985C3AA2E8}.Release|Any CPU.Build.0 = Release|Any CPU
{7DECE8E2-141A-4A14-A460-A7985C3AA2E8}.Release|x64.ActiveCfg = Release|Any CPU
{7DECE8E2-141A-4A14-A460-A7985C3AA2E8}.Release|x64.Build.0 = Release|Any CPU
{7DECE8E2-141A-4A14-A460-A7985C3AA2E8}.Release|x86.ActiveCfg = Release|Any CPU
{7DECE8E2-141A-4A14-A460-A7985C3AA2E8}.Release|x86.Build.0 = Release|Any CPU
{0C2E2EB0-8FA2-4AB9-8642-72E50A830DBA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0C2E2EB0-8FA2-4AB9-8642-72E50A830DBA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0C2E2EB0-8FA2-4AB9-8642-72E50A830DBA}.Debug|x64.ActiveCfg = Debug|Any CPU
{0C2E2EB0-8FA2-4AB9-8642-72E50A830DBA}.Debug|x64.Build.0 = Debug|Any CPU
{0C2E2EB0-8FA2-4AB9-8642-72E50A830DBA}.Debug|x86.ActiveCfg = Debug|Any CPU
{0C2E2EB0-8FA2-4AB9-8642-72E50A830DBA}.Debug|x86.Build.0 = Debug|Any CPU
{0C2E2EB0-8FA2-4AB9-8642-72E50A830DBA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0C2E2EB0-8FA2-4AB9-8642-72E50A830DBA}.Release|Any CPU.Build.0 = Release|Any CPU
{0C2E2EB0-8FA2-4AB9-8642-72E50A830DBA}.Release|x64.ActiveCfg = Release|Any CPU
{0C2E2EB0-8FA2-4AB9-8642-72E50A830DBA}.Release|x64.Build.0 = Release|Any CPU
{0C2E2EB0-8FA2-4AB9-8642-72E50A830DBA}.Release|x86.ActiveCfg = Release|Any CPU
{0C2E2EB0-8FA2-4AB9-8642-72E50A830DBA}.Release|x86.Build.0 = Release|Any CPU
{6482AE1A-896B-45A4-93D2-1DEA62120365}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6482AE1A-896B-45A4-93D2-1DEA62120365}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6482AE1A-896B-45A4-93D2-1DEA62120365}.Debug|x64.ActiveCfg = Debug|Any CPU
{6482AE1A-896B-45A4-93D2-1DEA62120365}.Debug|x64.Build.0 = Debug|Any CPU
{6482AE1A-896B-45A4-93D2-1DEA62120365}.Debug|x86.ActiveCfg = Debug|Any CPU
{6482AE1A-896B-45A4-93D2-1DEA62120365}.Debug|x86.Build.0 = Debug|Any CPU
{6482AE1A-896B-45A4-93D2-1DEA62120365}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6482AE1A-896B-45A4-93D2-1DEA62120365}.Release|Any CPU.Build.0 = Release|Any CPU
{6482AE1A-896B-45A4-93D2-1DEA62120365}.Release|x64.ActiveCfg = Release|Any CPU
{6482AE1A-896B-45A4-93D2-1DEA62120365}.Release|x64.Build.0 = Release|Any CPU
{6482AE1A-896B-45A4-93D2-1DEA62120365}.Release|x86.ActiveCfg = Release|Any CPU
{6482AE1A-896B-45A4-93D2-1DEA62120365}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal
================================================
FILE: LICENSE
================================================
MIT License
Copyright (c) 2017 Joseph Woodward
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.md
================================================

# GraphiQL.NET

GraphiQL middleware for ASP.NET Core - try the [live demo here](http://graphql.org/swapi-graphql/).
## What is GraphiQL.NET?
GraphiQL.NET is a piece of .NET Core middleware that bundles graphiql into it saving you from managing additional frontend dependencies, whilst also giving you control over the routes it's avaialble on any provide you with a means of authentication.
GraphiQL.NET features include:
- The full GraphiQl experience
- Customisation of GraphiQL routes
- Authentication

## Setup
The GraphiQL.NET middleware can be [found on NuGet here](https://www.nuget.org/packages/graphiql/)
You can install GraphiQL.NET by copying and pasting the following command into your Package Manager Console within Visual Studio (Tools > NuGet Package Manager > Package Manager Console).
```
Install-Package graphiql
```
Alternatively you can install it using the .NET Core CLI using the following command:
```
dotnet add package graphiql
```
## Getting Started
Once installed you can add GraphiQL.NET to your ASP.NET Core application by adding the `app.UseGraphiQl()` middleware to the `Configure` method within your `Startup.cs` file.
**Note: Be sure to call `UseGraphiQl()` before `UseMvc()`.**
```csharp
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
// Adding this makes graphiql UI available at /graphql
app.UseGraphiQl();
app.UseMvc();
}
```
## Configuration
---
### Configure Graphiql route
By default GraphiQL lives on the `/graphql` endpoint, however this can be changed by passing your chosen path to the `app.UseGraphiQl();` entry point method:
```csharp
app.UseGraphiQl('/whatever/graphiql');
```
### Configure Graphql API address
You can also specify GraphiQl endpoint independent of your GraphQL API, this is especially useful if you're hosting in IIS in a virtual application (ie `myapp.com/1.0/...`) or hosting API and documentation separately.
```csharp
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
app.UseGraphiQl("/graphql", "/v1/yourapi");
app.UseMvc();
}
```
Now navigating to `/graphql` will display the GraphiQL UI, but your GraphQL API will live under the `/v1/yourapi` route.
### Configuration via `IServiceCollection`
Alternatively you can configure the aforementioned routes via `IServiceCollection` within `ConfigureServices` or your `Startup.cs` file:
```csharp
//Startup.cs
public void ConfigureServices(IServiceCollection services)
{
...
services.AddGraphiQl(x =>
{
x.GraphiQlPath = "/graphiql-ui";
x.GraphQlApiPath = "graphql";
});
...
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory)
{
app.UseGraphiQl();
...
}
```
### Configuration via `ConfigureOptions<T>`
You can also use the `IConfigureOptions<T>` interface:
```csharp
// GraphiQlTestOptionsSetup.cs
internal class GraphiQlTestOptionsSetup : IConfigureOptions<GraphiQlOptions>
{
public void Configure(GraphiQlOptions options)
{
options.GraphiQlPath = "/graphiql-ui";
options.GraphQlApiPath = "graphql";
}
}
```
Then you just have to register it with your Ioc Container:
```csharp
//Startup.cs
public void ConfigureServices(IServiceCollection services)
{
...
services.AddTransient<IConfigureOptions<GraphiQlOptions>, GraphiQlTestOptionsSetup>();z
...
}
---
================================================
FILE: package.sh
================================================
#!/usr/bin/env bash
rm -rf ./package
dotnet pack ./src/GraphiQl/GraphiQl.csproj -o ./package/ -c release
================================================
FILE: src/GraphiQl/AssetProvider.cs
================================================
using System;
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Primitives;
namespace GraphiQl
{
internal class AssetProvider : IFileProvider
{
private readonly EmbeddedFileProvider _provider;
public AssetProvider(EmbeddedFileProvider provider)
=> _provider = provider;
public IFileInfo GetFileInfo(string subpath)
{
// Embedded resource renames hypphens in directory to underscore, this tells file provider where to find it.
if (subpath.Equals("/es6-promise/es6-promise.min.js", StringComparison.OrdinalIgnoreCase))
{
subpath = "/es6_promise/es6-promise.min.js";
}
return _provider.GetFileInfo(subpath);
}
public IDirectoryContents GetDirectoryContents(string subpath)
=> _provider.GetDirectoryContents(subpath);
public IChangeToken Watch(string filter)
=> _provider.Watch(filter);
}
}
================================================
FILE: src/GraphiQl/GraphiQl.csproj
================================================
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<AssemblyName>GraphiQL</AssemblyName>
<PackageId>GraphiQL</PackageId>
<PackageTags>graphql,graphiql,asp.net core,.net core</PackageTags>
<title>GraphiQL ASP.NET Core Middleware</title>
<TargetFrameworks>netstandard2.0;netcoreapp3.0;netcoreapp3.1</TargetFrameworks>
<Authors>JosephWoodward</Authors>
<Description>GraphiQL available as middleware for ASP.NET Core</Description>
<PackageIconUrl>https://raw.githubusercontent.com/JosephWoodward/graphiql-dotnet/master/assets/logo_128_128.png</PackageIconUrl>
<PackageProjectUrl>https://github.com/JosephWoodward/graphiql-dotnet</PackageProjectUrl>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>
<PackageIcon>logo_128_128.png</PackageIcon>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<PublishRepositoryUrl>true</PublishRepositoryUrl>
<MinVerVerbosity>diag</MinVerVerbosity>
<MinVerTagPrefix>v</MinVerTagPrefix>
<OutputType>Library</OutputType>
<MinVerSkip Condition="'$(Configuration)' == 'Debug'">true</MinVerSkip>
</PropertyGroup>
<ItemGroup>
<None Include="../../assets/logo_128_128.png" Pack="true" PackagePath="/" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="MinVer" Version="2.1.0">
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All">
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard2.0' ">
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.0.1" />
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="2.1.1" />
<PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="2.1.1" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netcoreapp3.0' ">
<FrameworkReference Include="Microsoft.AspNetCore.App" />
<PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="3.0.2" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netcoreapp3.1' ">
<FrameworkReference Include="Microsoft.AspNetCore.App" />
<PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="3.1.1" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="./assets/**/*.*" />
</ItemGroup>
</Project>
================================================
FILE: src/GraphiQl/GraphiQlExtensions.cs
================================================
using System;
using System.Reflection;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.StaticFiles;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Options;
namespace GraphiQl
{
public static class GraphiQlExtensions
{
/*
public static IServiceCollection AddGraphiQl(this IServiceCollection services)
=> services.AddGraphiQl(null);
*/
public static IServiceCollection AddGraphiQl(this IServiceCollection services, Action<GraphiQlOptions> configure)
{
if (configure != null)
{
services.Configure(configure);
}
services.TryAdd(ServiceDescriptor.Transient<IConfigureOptions<GraphiQlOptions>, GraphiQlOptionsSetup>());
return services;
}
public static IApplicationBuilder UseGraphiQl(this IApplicationBuilder app)
=> app.UseGraphiQl(null);
public static IApplicationBuilder UseGraphiQl(this IApplicationBuilder app, string path)
=> app.UseGraphiQl(path, null);
public static IApplicationBuilder UseGraphiQl(this IApplicationBuilder app, string path, string apiPath)
=> app.UseGraphiQlImp(path, apiPath);
private static IApplicationBuilder UseGraphiQlImp(this IApplicationBuilder app, string path, string apiPath )
{
if (app == null)
{
throw new ArgumentNullException(nameof(app));
}
var options = app.ApplicationServices.GetService<IOptions<GraphiQlOptions>>().Value;
var graphiQlPath = !string.IsNullOrWhiteSpace(path) ? path : options.GraphiQlPath;
var graphQlApiPath = !string.IsNullOrWhiteSpace(apiPath) ? apiPath : options.GraphQlApiPath;
var fileServerOptions = new FileServerOptions
{
RequestPath = graphiQlPath,
FileProvider = new AssetProvider(new EmbeddedFileProvider(typeof(GraphiQlExtensions).GetTypeInfo().Assembly, "GraphiQl.assets")),
EnableDefaultFiles = true,
StaticFileOptions = {ContentTypeProvider = new FileExtensionContentTypeProvider()}
};
app.UseMiddleware<GraphiQlMiddleware>();
app.Map($"{graphiQlPath.TrimEnd('/')}/graphql-path.js", x => WritePathJavaScript(x, graphQlApiPath));
app.UseFileServer(fileServerOptions);
return app;
}
private static void WritePathJavaScript(IApplicationBuilder app, string path)
=> app.Run(h =>
{
h.Response.ContentType = "application/javascript";
return h.Response.WriteAsync($"var graphqlPath='{path}';");
});
}
}
================================================
FILE: src/GraphiQl/GraphiQlMiddleware.cs
================================================
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Options;
namespace GraphiQl
{
public class GraphiQlMiddleware
{
private readonly RequestDelegate _next;
private readonly GraphiQlOptions _options;
public GraphiQlMiddleware(RequestDelegate next, IOptions<GraphiQlOptions> options)
{
_next = next;
_options = options.Value;
}
public async Task Invoke(HttpContext context)
{
if (context.Request.Path.Equals(_options.GraphiQlPath, StringComparison.OrdinalIgnoreCase)
&& _options.IsAuthenticated != null
&& !await _options.IsAuthenticated.Invoke(context))
{
return;
}
await _next(context);
}
}
}
================================================
FILE: src/GraphiQl/GraphiQlOptions.cs
================================================
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Options;
namespace GraphiQl
{
public class GraphiQlOptions
{
public string GraphiQlPath { get; set; }
public string GraphQlApiPath { get; set; }
public Func<HttpContext, Task<bool>> IsAuthenticated { get; set; }
public GraphiQlOptions()
{
GraphiQlPath = "/graphql";
GraphQlApiPath = "/graphql";
}
}
public class GraphiQlOptionsSetup : IConfigureOptions<GraphiQlOptions>
{
public void Configure(GraphiQlOptions options)
{
if (options.GraphiQlPath == null)
{
options.GraphiQlPath = "/graphql";
}
if (options.GraphQlApiPath == null)
{
options.GraphQlApiPath = "/graphql";
}
}
}
}
================================================
FILE: src/GraphiQl/assets/graphiql.css
================================================
.graphiql-container,
.graphiql-container button,
.graphiql-container input {
color: #141823;
font-family:
system,
-apple-system,
'San Francisco',
'.SFNSDisplay-Regular',
'Segoe UI',
Segoe,
'Segoe WP',
'Helvetica Neue',
helvetica,
'Lucida Grande',
arial,
sans-serif;
font-size: 14px;
}
.graphiql-container {
display: flex;
flex-direction: row;
height: 100%;
margin: 0;
overflow: hidden;
width: 100%;
}
.graphiql-container .editorWrap {
display: flex;
flex-direction: column;
flex: 1;
overflow-x: hidden;
}
.graphiql-container .title {
font-size: 18px;
}
.graphiql-container .title em {
font-family: georgia;
font-size: 19px;
}
.graphiql-container .topBarWrap {
display: flex;
flex-direction: row;
}
.graphiql-container .topBar {
align-items: center;
background: linear-gradient(#f7f7f7, #e2e2e2);
border-bottom: 1px solid #d0d0d0;
cursor: default;
display: flex;
flex-direction: row;
flex: 1;
height: 34px;
overflow-y: visible;
padding: 7px 14px 6px;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.graphiql-container .toolbar {
overflow-x: visible;
display: flex;
}
.graphiql-container .docExplorerShow,
.graphiql-container .historyShow {
background: linear-gradient(#f7f7f7, #e2e2e2);
border-radius: 0;
border-bottom: 1px solid #d0d0d0;
border-right: none;
border-top: none;
color: #3B5998;
cursor: pointer;
font-size: 14px;
margin: 0;
padding: 2px 20px 0 18px;
}
.graphiql-container .docExplorerShow {
border-left: 1px solid rgba(0, 0, 0, 0.2);
}
.graphiql-container .historyShow {
border-right: 1px solid rgba(0, 0, 0, 0.2);
border-left: 0;
}
.graphiql-container .docExplorerShow:before {
border-left: 2px solid #3B5998;
border-top: 2px solid #3B5998;
content: '';
display: inline-block;
height: 9px;
margin: 0 3px -1px 0;
position: relative;
transform: rotate(-45deg);
width: 9px;
}
.graphiql-container .editorBar {
display: flex;
flex-direction: row;
flex: 1;
}
.graphiql-container .queryWrap {
display: flex;
flex-direction: column;
flex: 1;
}
.graphiql-container .resultWrap {
border-left: solid 1px #e0e0e0;
display: flex;
flex-direction: column;
flex: 1;
flex-basis: 1em;
position: relative;
}
.graphiql-container .docExplorerWrap,
.graphiql-container .historyPaneWrap {
background: white;
box-shadow: 0 0 8px rgba(0, 0, 0, 0.15);
position: relative;
z-index: 3;
}
.graphiql-container .historyPaneWrap {
min-width: 230px;
z-index: 5;
}
.graphiql-container .docExplorerResizer {
cursor: col-resize;
height: 100%;
left: -5px;
position: absolute;
top: 0;
width: 10px;
z-index: 10;
}
.graphiql-container .docExplorerHide {
cursor: pointer;
font-size: 18px;
margin: -7px -8px -6px 0;
padding: 18px 16px 15px 12px;
background: 0;
border: 0;
line-height: 14px;
}
.graphiql-container div .query-editor {
flex: 1;
position: relative;
}
.graphiql-container .variable-editor {
display: flex;
flex-direction: column;
height: 30px;
position: relative;
}
.graphiql-container .variable-editor-title {
background: #eeeeee;
border-bottom: 1px solid #d6d6d6;
border-top: 1px solid #e0e0e0;
color: #777;
font-variant: small-caps;
font-weight: bold;
letter-spacing: 1px;
line-height: 14px;
padding: 6px 0 8px 43px;
text-transform: lowercase;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.graphiql-container .codemirrorWrap {
flex: 1;
height: 100%;
position: relative;
}
.graphiql-container .result-window {
flex: 1;
height: 100%;
position: relative;
}
.graphiql-container .footer {
background: #f6f7f8;
border-left: 1px solid #e0e0e0;
border-top: 1px solid #e0e0e0;
margin-left: 12px;
position: relative;
}
.graphiql-container .footer:before {
background: #eeeeee;
bottom: 0;
content: " ";
left: -13px;
position: absolute;
top: -1px;
width: 12px;
}
/* No `.graphiql-container` here so themes can overwrite */
.result-window .CodeMirror {
background: #f6f7f8;
}
.graphiql-container .result-window .CodeMirror-gutters {
background-color: #eeeeee;
border-color: #e0e0e0;
cursor: col-resize;
}
.graphiql-container .result-window .CodeMirror-foldgutter,
.graphiql-container .result-window .CodeMirror-foldgutter-open:after,
.graphiql-container .result-window .CodeMirror-foldgutter-folded:after {
padding-left: 3px;
}
.graphiql-container .toolbar-button {
background: #fdfdfd;
background: linear-gradient(#f9f9f9, #ececec);
border: 0;
border-radius: 3px;
box-shadow:
inset 0 0 0 1px rgba(0,0,0,0.20),
0 1px 0 rgba(255,255,255, 0.7),
inset 0 1px #fff;
color: #555;
cursor: pointer;
display: inline-block;
margin: 0 5px;
padding: 3px 11px 5px;
text-decoration: none;
text-overflow: ellipsis;
white-space: nowrap;
max-width: 150px;
}
.graphiql-container .toolbar-button:active {
background: linear-gradient(#ececec, #d5d5d5);
box-shadow:
0 1px 0 rgba(255, 255, 255, 0.7),
inset 0 0 0 1px rgba(0,0,0,0.10),
inset 0 1px 1px 1px rgba(0, 0, 0, 0.12),
inset 0 0 5px rgba(0, 0, 0, 0.1);
}
.graphiql-container .toolbar-button.error {
background: linear-gradient(#fdf3f3, #e6d6d7);
color: #b00;
}
.graphiql-container .toolbar-button-group {
margin: 0 5px;
white-space: nowrap;
}
.graphiql-container .toolbar-button-group > * {
margin: 0;
}
.graphiql-container .toolbar-button-group > *:not(:last-child) {
border-top-right-radius: 0;
border-bottom-right-radius: 0;
}
.graphiql-container .toolbar-button-group > *:not(:first-child) {
border-top-left-radius: 0;
border-bottom-left-radius: 0;
margin-left: -1px;
}
.graphiql-container .execute-button-wrap {
height: 34px;
margin: 0 14px 0 28px;
position: relative;
}
.graphiql-container .execute-button {
background: linear-gradient(#fdfdfd, #d2d3d6);
border-radius: 17px;
border: 1px solid rgba(0,0,0,0.25);
box-shadow: 0 1px 0 #fff;
cursor: pointer;
fill: #444;
height: 34px;
margin: 0;
padding: 0;
width: 34px;
}
.graphiql-container .execute-button svg {
pointer-events: none;
}
.graphiql-container .execute-button:active {
background: linear-gradient(#e6e6e6, #c3c3c3);
box-shadow:
0 1px 0 #fff,
inset 0 0 2px rgba(0, 0, 0, 0.2),
inset 0 0 6px rgba(0, 0, 0, 0.1);
}
.graphiql-container .toolbar-menu,
.graphiql-container .toolbar-select {
position: relative;
}
.graphiql-container .execute-options,
.graphiql-container .toolbar-menu-items,
.graphiql-container .toolbar-select-options {
background: #fff;
box-shadow:
0 0 0 1px rgba(0,0,0,0.1),
0 2px 4px rgba(0,0,0,0.25);
margin: 0;
padding: 6px 0;
position: absolute;
z-index: 100;
}
.graphiql-container .execute-options {
min-width: 100px;
top: 37px;
left: -1px;
}
.graphiql-container .toolbar-menu-items {
left: 1px;
margin-top: -1px;
min-width: 110%;
top: 100%;
visibility: hidden;
}
.graphiql-container .toolbar-menu-items.open {
visibility: visible;
}
.graphiql-container .toolbar-select-options {
left: 0;
min-width: 100%;
top: -5px;
visibility: hidden;
}
.graphiql-container .toolbar-select-options.open {
visibility: visible;
}
.graphiql-container .execute-options > li,
.graphiql-container .toolbar-menu-items > li,
.graphiql-container .toolbar-select-options > li {
cursor: pointer;
display: block;
margin: none;
max-width: 300px;
overflow: hidden;
padding: 2px 20px 4px 11px;
white-space: nowrap;
}
.graphiql-container .execute-options > li.selected,
.graphiql-container .toolbar-menu-items > li.hover,
.graphiql-container .toolbar-menu-items > li:active,
.graphiql-container .toolbar-menu-items > li:hover,
.graphiql-container .toolbar-select-options > li.hover,
.graphiql-container .toolbar-select-options > li:active,
.graphiql-container .toolbar-select-options > li:hover,
.graphiql-container .history-contents > li:hover,
.graphiql-container .history-contents > li:active {
background: #e10098;
color: #fff;
}
.graphiql-container .toolbar-select-options > li > svg {
display: inline;
fill: #666;
margin: 0 -6px 0 6px;
pointer-events: none;
vertical-align: middle;
}
.graphiql-container .toolbar-select-options > li.hover > svg,
.graphiql-container .toolbar-select-options > li:active > svg,
.graphiql-container .toolbar-select-options > li:hover > svg {
fill: #fff;
}
.graphiql-container .CodeMirror-scroll {
overflow-scrolling: touch;
}
.graphiql-container .CodeMirror {
color: #141823;
font-family:
'Consolas',
'Inconsolata',
'Droid Sans Mono',
'Monaco',
monospace;
font-size: 13px;
height: 100%;
left: 0;
position: absolute;
top: 0;
width: 100%;
}
.graphiql-container .CodeMirror-lines {
padding: 20px 0;
}
.CodeMirror-hint-information .content {
box-orient: vertical;
color: #141823;
display: flex;
font-family: system, -apple-system, 'San Francisco', '.SFNSDisplay-Regular', 'Segoe UI', Segoe, 'Segoe WP', 'Helvetica Neue', helvetica, 'Lucida Grande', arial, sans-serif;
font-size: 13px;
line-clamp: 3;
line-height: 16px;
max-height: 48px;
overflow: hidden;
text-overflow: -o-ellipsis-lastline;
}
.CodeMirror-hint-information .content p:first-child {
margin-top: 0;
}
.CodeMirror-hint-information .content p:last-child {
margin-bottom: 0;
}
.CodeMirror-hint-information .infoType {
color: #CA9800;
cursor: pointer;
display: inline;
margin-right: 0.5em;
}
.autoInsertedLeaf.cm-property {
animation-duration: 6s;
animation-name: insertionFade;
border-bottom: 2px solid rgba(255, 255, 255, 0);
border-radius: 2px;
margin: -2px -4px -1px;
padding: 2px 4px 1px;
}
@keyframes insertionFade {
from, to {
background: rgba(255, 255, 255, 0);
border-color: rgba(255, 255, 255, 0);
}
15%, 85% {
background: #fbffc9;
border-color: #f0f3c0;
}
}
div.CodeMirror-lint-tooltip {
background-color: white;
border-radius: 2px;
border: 0;
color: #141823;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.45);
font-size: 13px;
line-height: 16px;
max-width: 430px;
opacity: 0;
padding: 8px 10px;
transition: opacity 0.15s;
white-space: pre-wrap;
}
div.CodeMirror-lint-tooltip > * {
padding-left: 23px;
}
div.CodeMirror-lint-tooltip > * + * {
margin-top: 12px;
}
/* COLORS */
.graphiql-container .CodeMirror-foldmarker {
border-radius: 4px;
background: #08f;
background: linear-gradient(#43A8FF, #0F83E8);
box-shadow:
0 1px 1px rgba(0, 0, 0, 0.2),
inset 0 0 0 1px rgba(0, 0, 0, 0.1);
color: white;
font-family: arial;
font-size: 12px;
line-height: 0;
margin: 0 3px;
padding: 0px 4px 1px;
text-shadow: 0 -1px rgba(0, 0, 0, 0.1);
}
.graphiql-container div.CodeMirror span.CodeMirror-matchingbracket {
color: #555;
text-decoration: underline;
}
.graphiql-container div.CodeMirror span.CodeMirror-nonmatchingbracket {
color: #f00;
}
/* Comment */
.cm-comment {
color: #999;
}
/* Punctuation */
.cm-punctuation {
color: #555;
}
/* Keyword */
.cm-keyword {
color: #B11A04;
}
/* OperationName, FragmentName */
.cm-def {
color: #D2054E;
}
/* FieldName */
.cm-property {
color: #1F61A0;
}
/* FieldAlias */
.cm-qualifier {
color: #1C92A9;
}
/* ArgumentName and ObjectFieldName */
.cm-attribute {
color: #8B2BB9;
}
/* Number */
.cm-number {
color: #2882F9;
}
/* String */
.cm-string {
color: #D64292;
}
/* Boolean */
.cm-builtin {
color: #D47509;
}
/* EnumValue */
.cm-string-2 {
color: #0B7FC7;
}
/* Variable */
.cm-variable {
color: #397D13;
}
/* Directive */
.cm-meta {
color: #B33086;
}
/* Type */
.cm-atom {
color: #CA9800;
}
/* BASICS */
.CodeMirror {
/* Set height, width, borders, and global font properties here */
color: black;
font-family: monospace;
height: 300px;
}
/* PADDING */
.CodeMirror-lines {
padding: 4px 0; /* Vertical padding around content */
}
.CodeMirror pre {
padding: 0 4px; /* Horizontal padding of content */
}
.CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
background-color: white; /* The little square between H and V scrollbars */
}
/* GUTTER */
.CodeMirror-gutters {
border-right: 1px solid #ddd;
background-color: #f7f7f7;
white-space: nowrap;
}
.CodeMirror-linenumbers {}
.CodeMirror-linenumber {
color: #999;
min-width: 20px;
padding: 0 3px 0 5px;
text-align: right;
white-space: nowrap;
}
.CodeMirror-guttermarker { color: black; }
.CodeMirror-guttermarker-subtle { color: #999; }
/* CURSOR */
.CodeMirror .CodeMirror-cursor {
border-left: 1px solid black;
}
/* Shown when moving in bi-directional text */
.CodeMirror div.CodeMirror-secondarycursor {
border-left: 1px solid silver;
}
.CodeMirror.cm-fat-cursor div.CodeMirror-cursor {
background: #7e7;
border: 0;
width: auto;
}
.CodeMirror.cm-fat-cursor div.CodeMirror-cursors {
z-index: 1;
}
.cm-animate-fat-cursor {
animation: blink 1.06s steps(1) infinite;
border: 0;
width: auto;
}
@keyframes blink {
0% { background: #7e7; }
50% { background: none; }
100% { background: #7e7; }
}
/* Can style cursor different in overwrite (non-insert) mode */
div.CodeMirror-overwrite div.CodeMirror-cursor {}
.cm-tab { display: inline-block; text-decoration: inherit; }
.CodeMirror-ruler {
border-left: 1px solid #ccc;
position: absolute;
}
/* DEFAULT THEME */
.cm-s-default .cm-keyword {color: #708;}
.cm-s-default .cm-atom {color: #219;}
.cm-s-default .cm-number {color: #164;}
.cm-s-default .cm-def {color: #00f;}
.cm-s-default .cm-variable,
.cm-s-default .cm-punctuation,
.cm-s-default .cm-property,
.cm-s-default .cm-operator {}
.cm-s-default .cm-variable-2 {color: #05a;}
.cm-s-default .cm-variable-3 {color: #085;}
.cm-s-default .cm-comment {color: #a50;}
.cm-s-default .cm-string {color: #a11;}
.cm-s-default .cm-string-2 {color: #f50;}
.cm-s-default .cm-meta {color: #555;}
.cm-s-default .cm-qualifier {color: #555;}
.cm-s-default .cm-builtin {color: #30a;}
.cm-s-default .cm-bracket {color: #997;}
.cm-s-default .cm-tag {color: #170;}
.cm-s-default .cm-attribute {color: #00c;}
.cm-s-default .cm-header {color: blue;}
.cm-s-default .cm-quote {color: #090;}
.cm-s-default .cm-hr {color: #999;}
.cm-s-default .cm-link {color: #00c;}
.cm-negative {color: #d44;}
.cm-positive {color: #292;}
.cm-header, .cm-strong {font-weight: bold;}
.cm-em {font-style: italic;}
.cm-link {text-decoration: underline;}
.cm-strikethrough {text-decoration: line-through;}
.cm-s-default .cm-error {color: #f00;}
.cm-invalidchar {color: #f00;}
.CodeMirror-composing { border-bottom: 2px solid; }
/* Default styles for common addons */
div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;}
div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
.CodeMirror-matchingtag { background: rgba(255, 150, 0, .3); }
.CodeMirror-activeline-background {background: #e8f2ff;}
/* STOP */
/* The rest of this file contains styles related to the mechanics of
the editor. You probably shouldn't touch them. */
.CodeMirror {
background: white;
overflow: hidden;
position: relative;
}
.CodeMirror-scroll {
height: 100%;
/* 30px is the magic margin used to hide the element's real scrollbars */
/* See overflow: hidden in .CodeMirror */
margin-bottom: -30px; margin-right: -30px;
outline: none; /* Prevent dragging from highlighting the element */
overflow: scroll !important; /* Things will break if this is overridden */
padding-bottom: 30px;
position: relative;
}
.CodeMirror-sizer {
border-right: 30px solid transparent;
position: relative;
}
/* The fake, visible scrollbars. Used to force redraw during scrolling
before actual scrolling happens, thus preventing shaking and
flickering artifacts. */
.CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
display: none;
position: absolute;
z-index: 6;
}
.CodeMirror-vscrollbar {
overflow-x: hidden;
overflow-y: scroll;
right: 0; top: 0;
}
.CodeMirror-hscrollbar {
bottom: 0; left: 0;
overflow-x: scroll;
overflow-y: hidden;
}
.CodeMirror-scrollbar-filler {
right: 0; bottom: 0;
}
.CodeMirror-gutter-filler {
left: 0; bottom: 0;
}
.CodeMirror-gutters {
min-height: 100%;
position: absolute; left: 0; top: 0;
z-index: 3;
}
.CodeMirror-gutter {
display: inline-block;
height: 100%;
margin-bottom: -30px;
vertical-align: top;
white-space: normal;
/* Hack to make IE7 behave */
*zoom:1;
*display:inline;
}
.CodeMirror-gutter-wrapper {
background: none !important;
border: none !important;
position: absolute;
z-index: 4;
}
.CodeMirror-gutter-background {
position: absolute;
top: 0; bottom: 0;
z-index: 4;
}
.CodeMirror-gutter-elt {
cursor: default;
position: absolute;
z-index: 4;
}
.CodeMirror-gutter-wrapper {
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.CodeMirror-lines {
cursor: text;
min-height: 1px; /* prevents collapsing before first draw */
}
.CodeMirror pre {
-webkit-tap-highlight-color: transparent;
/* Reset some styles that the rest of the page might have set */
background: transparent;
border-radius: 0;
border-width: 0;
color: inherit;
font-family: inherit;
font-size: inherit;
font-variant-ligatures: none;
line-height: inherit;
margin: 0;
overflow: visible;
position: relative;
white-space: pre;
word-wrap: normal;
z-index: 2;
}
.CodeMirror-wrap pre {
word-wrap: break-word;
white-space: pre-wrap;
word-break: normal;
}
.CodeMirror-linebackground {
position: absolute;
left: 0; right: 0; top: 0; bottom: 0;
z-index: 0;
}
.CodeMirror-linewidget {
overflow: auto;
position: relative;
z-index: 2;
}
.CodeMirror-widget {}
.CodeMirror-code {
outline: none;
}
/* Force content-box sizing for the elements where we expect it */
.CodeMirror-scroll,
.CodeMirror-sizer,
.CodeMirror-gutter,
.CodeMirror-gutters,
.CodeMirror-linenumber {
box-sizing: content-box;
}
.CodeMirror-measure {
height: 0;
overflow: hidden;
position: absolute;
visibility: hidden;
width: 100%;
}
.CodeMirror-cursor { position: absolute; }
.CodeMirror-measure pre { position: static; }
div.CodeMirror-cursors {
position: relative;
visibility: hidden;
z-index: 3;
}
div.CodeMirror-dragcursors {
visibility: visible;
}
.CodeMirror-focused div.CodeMirror-cursors {
visibility: visible;
}
.CodeMirror-selected { background: #d9d9d9; }
.CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; }
.CodeMirror-crosshair { cursor: crosshair; }
.CodeMirror-line::selection, .CodeMirror-line > span::selection, .CodeMirror-line > span > span::selection { background: #d7d4f0; }
.CodeMirror-line::-moz-selection, .CodeMirror-line > span::-moz-selection, .CodeMirror-line > span > span::-moz-selection { background: #d7d4f0; }
.cm-searching {
background: #ffa;
background: rgba(255, 255, 0, .4);
}
/* IE7 hack to prevent it from returning funny offsetTops on the spans */
.CodeMirror span { *vertical-align: text-bottom; }
/* Used to force a border model for a node */
.cm-force-border { padding-right: .1px; }
@media print {
/* Hide the cursor when printing */
.CodeMirror div.CodeMirror-cursors {
visibility: hidden;
}
}
/* See issue #2901 */
.cm-tab-wrap-hack:after { content: ''; }
/* Help users use markselection to safely style text background */
span.CodeMirror-selectedtext { background: none; }
.CodeMirror-dialog {
background: inherit;
color: inherit;
left: 0; right: 0;
overflow: hidden;
padding: .1em .8em;
position: absolute;
z-index: 15;
}
.CodeMirror-dialog-top {
border-bottom: 1px solid #eee;
top: 0;
}
.CodeMirror-dialog-bottom {
border-top: 1px solid #eee;
bottom: 0;
}
.CodeMirror-dialog input {
background: transparent;
border: 1px solid #d3d6db;
color: inherit;
font-family: monospace;
outline: none;
width: 20em;
}
.CodeMirror-dialog button {
font-size: 70%;
}
.graphiql-container .doc-explorer {
background: white;
}
.graphiql-container .doc-explorer-title-bar,
.graphiql-container .history-title-bar {
cursor: default;
display: flex;
height: 34px;
line-height: 14px;
padding: 8px 8px 5px;
position: relative;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.graphiql-container .doc-explorer-title,
.graphiql-container .history-title {
flex: 1;
font-weight: bold;
overflow-x: hidden;
padding: 10px 0 10px 10px;
text-align: center;
text-overflow: ellipsis;
-webkit-user-select: text;
-moz-user-select: text;
-ms-user-select: text;
user-select: text;
white-space: nowrap;
}
.graphiql-container .doc-explorer-back {
color: #3B5998;
cursor: pointer;
margin: -7px 0 -6px -8px;
overflow-x: hidden;
padding: 17px 12px 16px 16px;
text-overflow: ellipsis;
white-space: nowrap;
background: 0;
border: 0;
line-height: 14px;
}
.doc-explorer-narrow .doc-explorer-back {
width: 0;
}
.graphiql-container .doc-explorer-back:before {
border-left: 2px solid #3B5998;
border-top: 2px solid #3B5998;
content: '';
display: inline-block;
height: 9px;
margin: 0 3px -1px 0;
position: relative;
transform: rotate(-45deg);
width: 9px;
}
.graphiql-container .doc-explorer-rhs {
position: relative;
}
.graphiql-container .doc-explorer-contents,
.graphiql-container .history-contents {
background-color: #ffffff;
border-top: 1px solid #d6d6d6;
bottom: 0;
left: 0;
overflow-y: auto;
padding: 20px 15px;
position: absolute;
right: 0;
top: 47px;
}
.graphiql-container .doc-explorer-contents {
min-width: 300px;
}
.graphiql-container .doc-type-description p:first-child ,
.graphiql-container .doc-type-description blockquote:first-child {
margin-top: 0;
}
.graphiql-container .doc-explorer-contents a {
cursor: pointer;
text-decoration: none;
}
.graphiql-container .doc-explorer-contents a:hover {
text-decoration: underline;
}
.graphiql-container .doc-value-description > :first-child {
margin-top: 4px;
}
.graphiql-container .doc-value-description > :last-child {
margin-bottom: 4px;
}
.graphiql-container .doc-type-description code,
.graphiql-container .doc-type-description pre,
.graphiql-container .doc-category code,
.graphiql-container .doc-category pre {
--saf-0: rgba(var(--sk_foreground_low,29,28,29),0.13);
font-size: 12px;
line-height: 1.50001;
font-variant-ligatures: none;
white-space: pre;
white-space: pre-wrap;
word-wrap: break-word;
word-break: normal;
-webkit-tab-size: 4;
-moz-tab-size: 4;
tab-size: 4;
}
.graphiql-container .doc-type-description code,
.graphiql-container .doc-category code {
padding: 2px 3px 1px;
border: 1px solid var(--saf-0);
border-radius: 3px;
background-color: rgba(var(--sk_foreground_min,29,28,29),.04);
color: #e01e5a;
background-color: white;
}
.graphiql-container .doc-category {
margin: 20px 0;
}
.graphiql-container .doc-category-title {
border-bottom: 1px solid #e0e0e0;
color: #777;
cursor: default;
font-size: 14px;
font-variant: small-caps;
font-weight: bold;
letter-spacing: 1px;
margin: 0 -15px 10px 0;
padding: 10px 0;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.graphiql-container .doc-category-item {
margin: 12px 0;
color: #555;
}
.graphiql-container .keyword {
color: #B11A04;
}
.graphiql-container .type-name {
color: #CA9800;
}
.graphiql-container .field-name {
color: #1F61A0;
}
.graphiql-container .field-short-description {
color: #999;
margin-left: 5px;
overflow: hidden;
text-overflow: ellipsis;
}
.graphiql-container .enum-value {
color: #0B7FC7;
}
.graphiql-container .arg-name {
color: #8B2BB9;
}
.graphiql-container .arg {
display: block;
margin-left: 1em;
}
.graphiql-container .arg:first-child:last-child,
.graphiql-container .arg:first-child:nth-last-child(2),
.graphiql-container .arg:first-child:nth-last-child(2) ~ .arg {
display: inherit;
margin: inherit;
}
.graphiql-container .arg:first-child:nth-last-child(2):after {
content: ', ';
}
.graphiql-container .arg-default-value {
color: #43A047;
}
.graphiql-container .doc-deprecation {
background: #fffae8;
box-shadow: inset 0 0 1px #bfb063;
color: #867F70;
line-height: 16px;
margin: 8px -8px;
max-height: 80px;
overflow: hidden;
padding: 8px;
border-radius: 3px;
}
.graphiql-container .doc-deprecation:before {
content: 'Deprecated:';
color: #c79b2e;
cursor: default;
display: block;
font-size: 9px;
font-weight: bold;
letter-spacing: 1px;
line-height: 1;
padding-bottom: 5px;
text-transform: uppercase;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.graphiql-container .doc-deprecation > :first-child {
margin-top: 0;
}
.graphiql-container .doc-deprecation > :last-child {
margin-bottom: 0;
}
.graphiql-container .show-btn {
-webkit-appearance: initial;
display: block;
border-radius: 3px;
border: solid 1px #ccc;
text-align: center;
padding: 8px 12px 10px;
width: 100%;
box-sizing: border-box;
background: #fbfcfc;
color: #555;
cursor: pointer;
}
.graphiql-container .search-box {
border-bottom: 1px solid #d3d6db;
display: block;
font-size: 14px;
margin: -15px -15px 12px 0;
position: relative;
}
.graphiql-container .search-box-icon {
cursor: pointer;
display: block;
font-size: 24px;
position: absolute;
top: -2px;
transform: rotate(-45deg);
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.graphiql-container .search-box .search-box-clear {
background-color: #d0d0d0;
border-radius: 12px;
color: #fff;
cursor: pointer;
font-size: 11px;
padding: 1px 5px 2px;
position: absolute;
right: 3px;
top: 8px;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
border: 0;
}
.graphiql-container .search-box .search-box-clear:hover {
background-color: #b9b9b9;
}
.graphiql-container .search-box > input {
border: none;
box-sizing: border-box;
font-size: 14px;
outline: none;
padding: 6px 24px 8px 20px;
width: 100%;
}
.graphiql-container .error-container {
font-weight: bold;
left: 0;
letter-spacing: 1px;
opacity: 0.5;
position: absolute;
right: 0;
text-align: center;
text-transform: uppercase;
top: 50%;
transform: translate(0, -50%);
}
.CodeMirror-foldmarker {
color: blue;
cursor: pointer;
font-family: arial;
line-height: .3;
text-shadow: #b9f 1px 1px 2px, #b9f -1px -1px 2px, #b9f 1px -1px 2px, #b9f -1px 1px 2px;
}
.CodeMirror-foldgutter {
width: .7em;
}
.CodeMirror-foldgutter-open,
.CodeMirror-foldgutter-folded {
cursor: pointer;
}
.CodeMirror-foldgutter-open:after {
content: "\25BE";
}
.CodeMirror-foldgutter-folded:after {
content: "\25B8";
}
.graphiql-container .history-contents {
font-family: 'Consolas', 'Inconsolata', 'Droid Sans Mono', 'Monaco', monospace;
}
.graphiql-container .history-contents {
margin: 0;
padding: 0;
}
.graphiql-container .history-contents li {
align-items: center;
display: flex;
font-size: 12px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
margin: 0;
padding: 8px;
border-bottom: 1px solid #e0e0e0;
}
.graphiql-container .history-contents li button:not(.history-label) {
display: none;
margin-left: 10px;
}
.graphiql-container .history-contents li:hover button:not(.history-label),
.graphiql-container .history-contents li:focus-within button:not(.history-label) {
display: inline-block;
}
.graphiql-container .history-contents input,
.graphiql-container .history-contents button {
padding: 0;
background: 0;
border: 0;
font-size: inherit;
font-family: inherit;
line-height: 14px;
color: inherit;
}
.graphiql-container .history-contents input {
flex-grow: 1;
}
.graphiql-container .history-contents input::-webkit-input-placeholder {
color: inherit;
}
.graphiql-container .history-contents input:-ms-input-placeholder {
color: inherit;
}
.graphiql-container .history-contents input::-ms-input-placeholder {
color: inherit;
}
.graphiql-container .history-contents input::placeholder {
color: inherit;
}
.graphiql-container .history-contents button {
cursor: pointer;
text-align: left;
}
.graphiql-container .history-contents .history-label {
flex-grow: 1;
overflow: hidden;
text-overflow: ellipsis;
}
.CodeMirror-info {
background: white;
border-radius: 2px;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.45);
box-sizing: border-box;
color: #555;
font-family:
system,
-apple-system,
'San Francisco',
'.SFNSDisplay-Regular',
'Segoe UI',
Segoe,
'Segoe WP',
'Helvetica Neue',
helvetica,
'Lucida Grande',
arial,
sans-serif;
font-size: 13px;
line-height: 16px;
margin: 8px -8px;
max-width: 400px;
opacity: 0;
overflow: hidden;
padding: 8px 8px;
position: fixed;
transition: opacity 0.15s;
z-index: 50;
}
.CodeMirror-info :first-child {
margin-top: 0;
}
.CodeMirror-info :last-child {
margin-bottom: 0;
}
.CodeMirror-info p {
margin: 1em 0;
}
.CodeMirror-info .info-description {
color: #777;
line-height: 16px;
margin-top: 1em;
max-height: 80px;
overflow: hidden;
}
.CodeMirror-info .info-deprecation {
background: #fffae8;
box-shadow: inset 0 1px 1px -1px #bfb063;
color: #867F70;
line-height: 16px;
margin: -8px;
margin-top: 8px;
max-height: 80px;
overflow: hidden;
padding: 8px;
}
.CodeMirror-info .info-deprecation-label {
color: #c79b2e;
cursor: default;
display: block;
font-size: 9px;
font-weight: bold;
letter-spacing: 1px;
line-height: 1;
padding-bottom: 5px;
text-transform: uppercase;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.CodeMirror-info .info-deprecation-label + * {
margin-top: 0;
}
.CodeMirror-info a {
text-decoration: none;
}
.CodeMirror-info a:hover {
text-decoration: underline;
}
.CodeMirror-info .type-name {
color: #CA9800;
}
.CodeMirror-info .field-name {
color: #1F61A0;
}
.CodeMirror-info .enum-value {
color: #0B7FC7;
}
.CodeMirror-info .arg-name {
color: #8B2BB9;
}
.CodeMirror-info .directive-name {
color: #B33086;
}
.CodeMirror-jump-token {
text-decoration: underline;
cursor: pointer;
}
/* The lint marker gutter */
.CodeMirror-lint-markers {
width: 16px;
}
.CodeMirror-lint-tooltip {
background-color: infobackground;
border-radius: 4px 4px 4px 4px;
border: 1px solid black;
color: infotext;
font-family: monospace;
font-size: 10pt;
max-width: 600px;
opacity: 0;
overflow: hidden;
padding: 2px 5px;
position: fixed;
transition: opacity .4s;
white-space: pre-wrap;
z-index: 100;
}
.CodeMirror-lint-mark-error, .CodeMirror-lint-mark-warning {
background-position: left bottom;
background-repeat: repeat-x;
}
.CodeMirror-lint-mark-error {
background-image:
url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAYAAAC09K7GAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sJDw4cOCW1/KIAAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAAHElEQVQI12NggIL/DAz/GdA5/xkY/qPKMDAwAADLZwf5rvm+LQAAAABJRU5ErkJggg==")
;
}
.CodeMirror-lint-mark-warning {
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAYAAAC09K7GAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sJFhQXEbhTg7YAAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAAMklEQVQI12NkgIIvJ3QXMjAwdDN+OaEbysDA4MPAwNDNwMCwiOHLCd1zX07o6kBVGQEAKBANtobskNMAAAAASUVORK5CYII=");
}
.CodeMirror-lint-marker-error, .CodeMirror-lint-marker-warning {
background-position: center center;
background-repeat: no-repeat;
cursor: pointer;
display: inline-block;
height: 16px;
position: relative;
vertical-align: middle;
width: 16px;
}
.CodeMirror-lint-message-error, .CodeMirror-lint-message-warning {
background-position: top left;
background-repeat: no-repeat;
padding-left: 18px;
}
.CodeMirror-lint-marker-error, .CodeMirror-lint-message-error {
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAHlBMVEW7AAC7AACxAAC7AAC7AAAAAAC4AAC5AAD///+7AAAUdclpAAAABnRSTlMXnORSiwCK0ZKSAAAATUlEQVR42mWPOQ7AQAgDuQLx/z8csYRmPRIFIwRGnosRrpamvkKi0FTIiMASR3hhKW+hAN6/tIWhu9PDWiTGNEkTtIOucA5Oyr9ckPgAWm0GPBog6v4AAAAASUVORK5CYII=");
}
.CodeMirror-lint-marker-warning, .CodeMirror-lint-message-warning {
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAANlBMVEX/uwDvrwD/uwD/uwD/uwD/uwD/uwD/uwD/uwD6twD/uwAAAADurwD2tQD7uAD+ugAAAAD/uwDhmeTRAAAADHRSTlMJ8mN1EYcbmiixgACm7WbuAAAAVklEQVR42n3PUQqAIBBFUU1LLc3u/jdbOJoW1P08DA9Gba8+YWJ6gNJoNYIBzAA2chBth5kLmG9YUoG0NHAUwFXwO9LuBQL1giCQb8gC9Oro2vp5rncCIY8L8uEx5ZkAAAAASUVORK5CYII=");
}
.CodeMirror-lint-marker-multiple {
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAcAAAAHCAMAAADzjKfhAAAACVBMVEUAAAAAAAC/v7914kyHAAAAAXRSTlMAQObYZgAAACNJREFUeNo1ioEJAAAIwmz/H90iFFSGJgFMe3gaLZ0od+9/AQZ0ADosbYraAAAAAElFTkSuQmCC");
background-position: right bottom;
background-repeat: no-repeat;
width: 100%; height: 100%;
}
.graphiql-container .spinner-container {
height: 36px;
left: 50%;
position: absolute;
top: 50%;
transform: translate(-50%, -50%);
width: 36px;
z-index: 10;
}
.graphiql-container .spinner {
animation: rotation .6s infinite linear;
border-bottom: 6px solid rgba(150, 150, 150, .15);
border-left: 6px solid rgba(150, 150, 150, .15);
border-radius: 100%;
border-right: 6px solid rgba(150, 150, 150, .15);
border-top: 6px solid rgba(150, 150, 150, .8);
display: inline-block;
height: 24px;
position: absolute;
vertical-align: middle;
width: 24px;
}
@keyframes rotation {
from { transform: rotate(0deg); }
to { transform: rotate(359deg); }
}
.CodeMirror-hints {
background: white;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.45);
font-family: 'Consolas', 'Inconsolata', 'Droid Sans Mono', 'Monaco', monospace;
font-size: 13px;
list-style: none;
margin-left: -6px;
margin: 0;
max-height: 14.5em;
overflow-y: auto;
overflow: hidden;
padding: 0;
position: absolute;
z-index: 10;
}
.CodeMirror-hint {
border-top: solid 1px #f7f7f7;
color: #141823;
cursor: pointer;
margin: 0;
max-width: 300px;
overflow: hidden;
padding: 2px 6px;
white-space: pre;
}
li.CodeMirror-hint-active {
background-color: #08f;
border-top-color: white;
color: white;
}
.CodeMirror-hint-information {
border-top: solid 1px #c0c0c0;
max-width: 300px;
padding: 4px 6px;
position: relative;
z-index: 1;
}
.CodeMirror-hint-information:first-child {
border-bottom: solid 1px #c0c0c0;
border-top: none;
margin-bottom: -1px;
}
.CodeMirror-hint-deprecation {
background: #fffae8;
box-shadow: inset 0 1px 1px -1px #bfb063;
color: #867F70;
font-family:
system,
-apple-system,
'San Francisco',
'.SFNSDisplay-Regular',
'Segoe UI',
Segoe,
'Segoe WP',
'Helvetica Neue',
helvetica,
'Lucida Grande',
arial,
sans-serif;
font-size: 13px;
line-height: 16px;
margin-top: 4px;
max-height: 80px;
overflow: hidden;
padding: 6px;
}
.CodeMirror-hint-deprecation .deprecation-label {
color: #c79b2e;
cursor: default;
display: block;
font-size: 9px;
font-weight: bold;
letter-spacing: 1px;
line-height: 1;
padding-bottom: 5px;
text-transform: uppercase;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.CodeMirror-hint-deprecation .deprecation-label + * {
margin-top: 0;
}
.CodeMirror-hint-deprecation :last-child {
margin-bottom: 0;
}
================================================
FILE: src/GraphiQl/assets/index.html
================================================
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="robots" content="noindex" />
<meta name="referrer" content="origin" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>GraphQL API</title>
<style>
body {
height: 100vh;
margin: 0;
overflow: hidden;
}
#splash {
color: #333;
display: flex;
flex-direction: column;
font-family: system, -apple-system, "San Francisco", ".SFNSDisplay-Regular", "Segoe UI", Segoe, "Segoe WP", "Helvetica Neue", helvetica, "Lucida Grande", arial, sans-serif;
height: 100vh;
justify-content: center;
text-align: center;
}
</style>
<link rel="icon" href="favicon.ico">
<link type="text/css" href="./graphiql.css" rel="stylesheet" />
</head>
<body>
<div id="splash">
Loading…
</div>
<script src="./es6-promise/es6-promise.min.js"></script>
<script src="./react/react.min.js"></script>
<script src="./react/react-dom.min.js"></script>
<script src="./graphiql.min.js"></script>
<script src="./graphql-path.js"></script>
<script>
// Parse the search string to get url parameters.
var search = window.location.search;
var parameters = {};
search.substr(1).split('&').forEach(function (entry) {
var eq = entry.indexOf('=');
if (eq >= 0) {
parameters[decodeURIComponent(entry.slice(0, eq))] =
decodeURIComponent(entry.slice(eq + 1));
}
});
// if variables was provided, try to format it.
if (parameters.variables) {
try {
parameters.variables =
JSON.stringify(JSON.parse(parameters.variables), null, 2);
} catch (e) {
// Do nothing, we want to display the invalid JSON as a string, rather
// than present an error.
}
}
// When the query and variables string is edited, update the URL bar so
// that it can be easily shared
function onEditQuery(newQuery) {
parameters.query = newQuery;
updateURL();
}
function onEditVariables(newVariables) {
parameters.variables = newVariables;
updateURL();
}
function onEditOperationName(newOperationName) {
parameters.operationName = newOperationName;
updateURL();
}
function updateURL() {
var newSearch = '?' + Object.keys(parameters).filter(function (key) {
return Boolean(parameters[key]);
}).map(function (key) {
return encodeURIComponent(key) + '=' +
encodeURIComponent(parameters[key]);
}).join('&');
history.replaceState(null, null, newSearch);
}
function graphQLFetcher(graphQLParams) {
// This example expects a GraphQL server at the path /graphql.
// Change this to point wherever you host your GraphQL server.
return fetch(graphqlPath, {
method: 'post',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(graphQLParams),
}).then(function (response) {
return response.text();
}).then(function (responseBody) {
try {
return JSON.parse(responseBody);
} catch (error) {
return responseBody;
}
});
}
// Render <GraphiQL /> into the body.
ReactDOM.render(
React.createElement(GraphiQL, {
fetcher: graphQLFetcher,
query: parameters.query,
variables: parameters.variables,
operationName: parameters.operationName,
onEditQuery: onEditQuery,
onEditVariables: onEditVariables,
onEditOperationName: onEditOperationName
}),
document.body,
);
</script>
</body>
</html>
================================================
FILE: tests/GraphiQl.Demo/.bowerrc
================================================
{
"directory": "wwwroot/lib"
}
================================================
FILE: tests/GraphiQl.Demo/Controllers/GraphQlController.cs
================================================
using System.Threading.Tasks;
using GraphiQl.Demo.GraphQl;
using GraphiQl.Demo.GraphQl.Models;
using GraphQL;
using GraphQL.Types;
using Microsoft.AspNetCore.Mvc;
namespace GraphiQl.Demo.Controllers
{
[Route(Startup.GraphQlPath)]
[Route(Startup.CustomGraphQlPath)]
public class GraphQlController : Controller
{
[HttpPost]
public async Task<IActionResult> Post([FromBody] GraphQlQuery query)
{
var schema = new Schema {Query = new StarWarsQuery()};
var result = await new DocumentExecuter().ExecuteAsync(x =>
{
x.Schema = schema;
x.Query = query.Query;
x.Inputs = query.Variables;
});
if (result.Errors?.Count > 0)
{
return BadRequest();
}
return Ok(result);
}
}
}
================================================
FILE: tests/GraphiQl.Demo/GraphQl/Droid.cs
================================================
namespace GraphiQl.Demo.GraphQl
{
public class Droid
{
public int Id { get; set; }
public string Name { get; set; }
}
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
}
}
================================================
FILE: tests/GraphiQl.Demo/GraphQl/GraphQlQuery.cs
================================================
using GraphQL;
namespace GraphiQl.Demo.GraphQl
{
public class GraphQlQuery
{
public string OperationName { get; set; }
public string NamedQuery { get; set; }
public string Query { get; set; }
public Inputs Variables { get; set; }
}
}
================================================
FILE: tests/GraphiQl.Demo/GraphQl/Models/DroidType.cs
================================================
using GraphQL.Types;
namespace GraphiQl.Demo.GraphQl.Models
{
public class DroidType : ObjectGraphType<Droid>
{
public DroidType()
{
Field(x => x.Id).Description("The Id of the Droid.");
Field(x => x.Name, nullable: true).Description("The name of the Droid.");
}
}
public class PersonType : ObjectGraphType<Person>
{
public PersonType()
{
// Field(x => x.FirstName).Resolve((x) => {
// return "Hello!";
// }).Description("Perso's First Name");
Field(x => x.Id).Description("Peron's Id");
Field(x => x.Name).Description("Person's name");
Field(x => x.Age).Resolve(x => {
return 25;
}).Description("A person's age");
}
}
}
================================================
FILE: tests/GraphiQl.Demo/GraphQl/Models/StarWarsQuery.cs
================================================
using GraphQL.Types;
namespace GraphiQl.Demo.GraphQl.Models
{
public class StarWarsQuery : ObjectGraphType
{
public StarWarsQuery()
{
Field<DroidType>("hero", resolve: context => new Droid { Id = 1, Name = "R2-D2" });
Field<PersonType>("person", resolve: context => new Person { Id = 1, Name = "Mr Happy", Age = 32 });
// Field<PersonType>("person", resolve: context => new Person { Id = 5, FirstName = "Joe", Surname = "Woodward", Age = 32 });
}
}
}
================================================
FILE: tests/GraphiQl.Demo/GraphiQl.Demo.csproj
================================================
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="GraphQL" Version="2.4.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="3.1.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\GraphiQl\GraphiQl.csproj" />
</ItemGroup>
</Project>
================================================
FILE: tests/GraphiQl.Demo/Program.cs
================================================
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
namespace GraphiQl.Demo
{
public class Program
{
public static void Main(string[] args)
{
BuildWebHost(args).Run();
}
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.Build();
}
}
================================================
FILE: tests/GraphiQl.Demo/Properties/launchSettings.json
================================================
{
"profiles": {
"GraphiQl.Demp": {
"commandName": "Project",
"launchBrowser": true,
"launchUrl": "graphql",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "http://localhost:5000"
}
}
}
================================================
FILE: tests/GraphiQl.Demo/Startup.cs
================================================
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
namespace GraphiQl.Demo
{
public class Startup
{
public const string GraphQlPath = "/graphql";
public const string CustomGraphQlPath = "/custom-path";
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public virtual void ConfigureGraphQl(IServiceCollection services) {}
public void ConfigureServices(IServiceCollection services)
{
services
.AddMvc()
.AddNewtonsoftJson(
options => options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore
);
ConfigureGraphQl(services);
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory)
{
app.UseGraphiQl();
app.UseRouting().UseEndpoints(
routing => routing.MapControllers()
);
}
}
}
================================================
FILE: tests/GraphiQl.Demo/appsettings.Development.json
================================================
{
"Logging": {
"IncludeScopes": false,
"LogLevel": {
"Default": "Debug",
"System": "Information",
"Microsoft": "Information"
}
}
}
================================================
FILE: tests/GraphiQl.Demo/appsettings.json
================================================
{
"Logging": {
"IncludeScopes": false,
"LogLevel": {
"Default": "Warning"
}
}
}
================================================
FILE: tests/GraphiQl.Tests/AuthenticationTest/ConfigureOptionsSetup.cs
================================================
using System;
using System.Threading;
using System.Threading.Tasks;
using GraphiQl.Demo;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Shouldly;
using Xunit;
namespace GraphiQl.Tests.AuthenticationTest
{
public class ConfigureOptionsSetup : SeleniumTest, IAsyncLifetime
{
private readonly IWebHost _host;
public ConfigureOptionsSetup()
{
_host = WebHost.CreateDefaultBuilder()
.ConfigureServices(x => { x.AddTransient<IConfigureOptions<GraphiQlOptions>,GraphiQlTestOptionsSetup>(); })
.UseStartup<Startup>()
.UseKestrel()
.UseUrls("http://*:5001")
.Build();
}
[Fact]
public void RequiresAuthentication()
{
// Arrange + Act
var result = string.Empty;
RunTest(driver =>
{
driver.Navigate().GoToUrl("http://localhost:5001/graphql");
driver.Manage()
.Timeouts()
.ImplicitWait = TimeSpan.FromSeconds(2);
result = driver.PageSource;
});
// Assert
result.ShouldContain("This page requires authentication");
}
public async Task InitializeAsync()
=> await _host.StartAsync().ConfigureAwait(false);
public Task DisposeAsync()
{
_host.Dispose();
return Task.CompletedTask;
}
internal class GraphiQlTestOptionsSetup : IConfigureOptions<GraphiQlOptions>
{
public void Configure(GraphiQlOptions options)
{
options.IsAuthenticated = context =>
{
context.Response.Clear();
context.Response.StatusCode = 400;
context.Response.WriteAsync("This page requires authentication");
return Task.FromResult(false);
};
}
}
}
}
================================================
FILE: tests/GraphiQl.Tests/AuthenticationTest/DelegateSetup.cs
================================================
using System;
using System.Threading;
using System.Threading.Tasks;
using GraphiQl.Demo;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Shouldly;
using Xunit;
namespace GraphiQl.Tests.AuthenticationTest
{
public class CustomStartup : Startup
{
public CustomStartup(IConfiguration configuration) : base(configuration) {}
public override void ConfigureGraphQl(IServiceCollection services)
=> services.AddGraphiQl(x => x.IsAuthenticated = context =>
{
context.Response.Clear();
context.Response.StatusCode = 400;
context.Response.WriteAsync("This page requires authentication");
return Task.FromResult(false);
});
}
public class DelegateSetup : SeleniumTest, IAsyncLifetime
{
private readonly IWebHost _host;
public DelegateSetup()
{
_host = WebHost.CreateDefaultBuilder()
.UseStartup<CustomStartup>()
.UseKestrel()
.UseUrls("http://*:5001")
.Build();
}
[Fact]
public void RequiresAuthentication()
{
// Arrange + Act
var result = string.Empty;
RunTest(driver =>
{
driver.Navigate().GoToUrl("http://localhost:5001/graphql");
driver.Manage()
.Timeouts()
.ImplicitWait = TimeSpan.FromSeconds(2);
result = driver.PageSource;
});
// Assert
result.ShouldContain("This page requires authentication");
}
public async Task InitializeAsync()
=> await _host.StartAsync().ConfigureAwait(false);
public Task DisposeAsync()
{
_host.Dispose();
return Task.CompletedTask;
}
}
}
================================================
FILE: tests/GraphiQl.Tests/BasicTest.cs
================================================
using System;
using System.Text.Json;
using System.Threading;
using GraphiQl.Tests.Fixtures;
using Shouldly;
using Xunit;
namespace GraphiQl.Tests
{
public class BasicTest : SeleniumTest, IClassFixture<HostFixture>
{
private readonly HostFixture _fixture;
public BasicTest(HostFixture fixture)
{
_fixture = fixture;
}
[Fact]
public void CanQueryGraphQl()
{
// TODO: Use PageModel
// Arrange
var result = string.Empty;
var query = @"{hero{id,name}}";
// Act
RunTest( driver =>
{
driver.Navigate().GoToUrl(_fixture.GraphiQlUri + Uri.EscapeDataString(query));
var button = driver.FindElementByClassName("execute-button");
button?.Click();
//TODO: https://www.selenium.dev/documentation/en/webdriver/waits/
Thread.Sleep(2000);
// UGH!
result = driver.FindElementByClassName("result-window").Text
.Replace("\n", "")
.Replace(" ", "");
});
// Assert
using var channelResponse = JsonDocument.Parse(result);
var data = channelResponse.RootElement.GetProperty("data");
data.GetProperty("hero").GetProperty("name").GetString().ShouldBe("R2-D2");
}
}
}
================================================
FILE: tests/GraphiQl.Tests/Fixtures/GraphQlFixture.cs
================================================
using System.Threading.Tasks;
using GraphiQl;
using GraphiQl.Demo;
using GraphiQl.Demo.Controllers;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc.ApplicationParts;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Newtonsoft.Json;
namespace graphiql.Tests.Fixtures
{
public class GraphQlFixture
{
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseKestrel();
webBuilder.UseUrls("http://*:5000");
webBuilder.UseStartup<Startup>();
});
public async Task CreateKestrel()
{
var x = new WebHostBuilder();
var host = CreateHostBuilder(null).Build();
await host.RunAsync();
}
public IWebHost CreateWebHostOld()
{
var config = new ConfigurationBuilder().Build();
var host = new WebHostBuilder()
.UseConfiguration(config)
.ConfigureServices(s =>
{
s.AddMvc()
.AddNewtonsoftJson(o =>
o.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore);
s.AddControllers()
.PartManager.ApplicationParts.Add(new AssemblyPart(typeof(GraphQlController).Assembly));
})
.Configure(app =>
{
app.UseGraphiQl();
app.UseRouting().UseEndpoints(routing => routing.MapControllers());
});
return host.Build();
}
}
}
================================================
FILE: tests/GraphiQl.Tests/Fixtures/HostFixture.cs
================================================
using System.Threading.Tasks;
using GraphiQl.Demo;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Xunit;
namespace GraphiQl.Tests.Fixtures
{
public class HostFixture : IAsyncLifetime
{
private readonly IWebHost _host;
public string GraphiQlUri { get; } = "http://localhost:5001/graphql?query=";
public HostFixture()
{
_host = WebHost.CreateDefaultBuilder()
.UseStartup<Startup>()
.UseKestrel()
.UseUrls("http://*:5001")
.Build();
}
public async Task InitializeAsync()
=> await _host.StartAsync().ConfigureAwait(false);
public async Task DisposeAsync()
{
await _host.StopAsync().ConfigureAwait(false);
_host.Dispose();
}
}
}
================================================
FILE: tests/GraphiQl.Tests/GraphiQl.Tests.csproj
================================================
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<IsPackable>false</IsPackable>
<AssemblyName>GraphiQl.Tests</AssemblyName>
<RootNamespace>GraphiQl.Tests</RootNamespace>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.TestHost" Version="3.1.2" />
<PackageReference Include="Selenium.WebDriver" Version="3.141.0" />
<PackageReference Include="Selenium.WebDriver.ChromeDriver" Version="80.0.3987.10600" />
<PackageReference Include="Shouldly" Version="3.0.2" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.5.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="3.1.2" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\GraphiQl.Demo\GraphiQl.Demo.csproj" />
</ItemGroup>
</Project>
================================================
FILE: tests/GraphiQl.Tests/OverrideGraphQlPathTests/ConfigureOptionsSetup.cs
================================================
using System;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using GraphiQl.Demo;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Shouldly;
using Xunit;
namespace GraphiQl.Tests.OverrideGraphQlPathTests
{
public class ConfigureOptionsSetup : SeleniumTest, IAsyncLifetime
{
private readonly IWebHost _host;
public ConfigureOptionsSetup()
{
_host = WebHost.CreateDefaultBuilder()
.ConfigureServices(serviceCollection =>
{
serviceCollection.AddTransient<IConfigureOptions<GraphiQlOptions>, GraphiQlTestOptionsSetup>();
})
.UseStartup<Startup>()
.UseKestrel()
.UseUrls("http://*:5001")
.Build();
}
public async Task InitializeAsync()
=> await _host.StartAsync().ConfigureAwait(false);
[Fact]
public void CanOverrideGraphQlPath()
{
// TODO: Use PageModel
// Arrange
var result = string.Empty;
var query = @"{hero{id,name}}";
// Act
RunTest( driver =>
{
driver.Navigate().GoToUrl($"http://localhost:5001/graphql?query=" + Uri.EscapeDataString(query));
var button = driver.FindElementByClassName("execute-button");
button?.Click();
Thread.Sleep(2000);
/*
var x = Driver.FindElement(B)
var foo = new WebDriverWait(driver, TimeSpan.FromSeconds(3))
.Until(drv => drv.FindElement(By.Name("q")));
*/
// UGH!
result = driver
.FindElementByClassName("result-window").Text
.Replace("\n", "")
.Replace(" ", "");
});
// Assert
using var channelResponse = JsonDocument.Parse(result);
var data = channelResponse.RootElement.GetProperty("data");
data.GetProperty("hero").GetProperty("name").GetString().ShouldBe("R2-D2");
}
public async Task DisposeAsync()
{
await _host.StopAsync();
_host.Dispose();
}
internal class GraphiQlTestOptionsSetup : IConfigureOptions<GraphiQlOptions>
{
public void Configure(GraphiQlOptions options)
{
options.GraphQlApiPath = Startup.CustomGraphQlPath;
}
}
}
}
================================================
FILE: tests/GraphiQl.Tests/OverrideGraphQlPathTests/DelegateSetup.cs
================================================
using System;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using GraphiQl.Demo;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Shouldly;
using Xunit;
namespace GraphiQl.Tests.OverrideGraphQlPathTests
{
public class CustomStartup : Startup
{
public CustomStartup(IConfiguration configuration) : base(configuration) {}
public override void ConfigureGraphQl(IServiceCollection services)
=> services.AddGraphiQl(x => x.GraphQlApiPath = CustomGraphQlPath);
}
public class DelegateSetup : SeleniumTest, IAsyncLifetime
{
private readonly IWebHost _host;
public DelegateSetup()
{
_host = WebHost.CreateDefaultBuilder()
.UseStartup<CustomStartup>()
.UseKestrel()
.UseUrls("http://*:5001")
.Build();
}
public async Task InitializeAsync()
=> await _host.StartAsync().ConfigureAwait(false);
[Fact]
public void CanOverrideGraphQlPath()
{
// TODO: Use PageModel
// Arrange
var result = string.Empty;
var query = @"{hero{id,name}}";
// Act
RunTest( driver =>
{
driver.Navigate().GoToUrl("http://localhost:5001/graphql?query=" + Uri.EscapeDataString(query));
var button = driver.FindElementByClassName("execute-button");
button?.Click();
Thread.Sleep(2000);
// UGH!
result = driver
.FindElementByClassName("result-window").Text
.Replace("\n", "")
.Replace(" ", "");
});
// Assert
using var channelResponse = JsonDocument.Parse(result);
var data = channelResponse.RootElement.GetProperty("data");
data.GetProperty("hero").GetProperty("name").GetString().ShouldBe("R2-D2");
}
public async Task DisposeAsync()
{
await _host.StopAsync();
_host.Dispose();
}
}
}
================================================
FILE: tests/GraphiQl.Tests/OverrideGraphiQlPathTests/ConfigureOptionsSetup.cs
================================================
using System;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using GraphiQl.Demo;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Shouldly;
using Xunit;
namespace GraphiQl.Tests.OverrideGraphiQlPathTests
{
public class ConfigureOptionsSetup : SeleniumTest, IAsyncLifetime
{
private readonly IWebHost _host;
public ConfigureOptionsSetup()
{
_host = WebHost.CreateDefaultBuilder()
.ConfigureServices(serviceCollection =>
{
serviceCollection.AddTransient<IConfigureOptions<GraphiQlOptions>, GraphiQlTestOptionsSetup>();
})
.UseStartup<Startup>()
.UseKestrel()
.UseUrls("http://*:5001")
.Build();
}
public async Task InitializeAsync()
=> await _host.StartAsync().ConfigureAwait(false);
[Fact]
public void CanOverrideGraphiQlPath()
{
// TODO: Use PageModel
// Arrange
var result = string.Empty;
var query = @"{hero{id,name}}";
// Act
RunTest( driver =>
{
driver.Navigate().GoToUrl($"http://localhost:5001{Startup.CustomGraphQlPath}?query=" + Uri.EscapeDataString(query));
var button = driver.FindElementByClassName("execute-button");
button?.Click();
Thread.Sleep(2000);
// UGH!
result = driver
.FindElementByClassName("result-window").Text
.Replace("\n", "")
.Replace(" ", "");
});
// Assert
using var channelResponse = JsonDocument.Parse(result);
var data = channelResponse.RootElement.GetProperty("data");
data.GetProperty("hero").GetProperty("name").GetString().ShouldBe("R2-D2");
}
public async Task DisposeAsync()
{
await _host.StopAsync();
_host.Dispose();
}
internal class GraphiQlTestOptionsSetup : IConfigureOptions<GraphiQlOptions>
{
public void Configure(GraphiQlOptions options)
{
options.GraphiQlPath = Startup.CustomGraphQlPath;
}
}
}
}
================================================
FILE: tests/GraphiQl.Tests/OverrideGraphiQlPathTests/DelegateSetup.cs
================================================
using System;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using GraphiQl.Demo;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Shouldly;
using Xunit;
namespace GraphiQl.Tests.OverrideGraphiQlPathTests
{
public class CustomStartup : Startup
{
public CustomStartup(IConfiguration configuration) : base(configuration) {}
public override void ConfigureGraphQl(IServiceCollection services)
=> services.AddGraphiQl(x => x.GraphiQlPath = CustomGraphQlPath);
}
public class DelegateSetup : SeleniumTest, IAsyncLifetime
{
private readonly IWebHost _host;
public DelegateSetup()
{
_host = WebHost.CreateDefaultBuilder()
.UseStartup<CustomStartup>()
.UseKestrel()
.UseUrls("http://*:5001")
.Build();
}
public async Task InitializeAsync()
=> await _host.StartAsync().ConfigureAwait(false);
[Fact]
public void CanOverrideGraphiQlPath()
{
// TODO: Use PageModel
// Arrange
var result = string.Empty;
var query = @"{hero{id,name}}";
// Act
RunTest( driver =>
{
driver.Navigate().GoToUrl($"http://localhost:5001{Startup.CustomGraphQlPath}?query=" + Uri.EscapeDataString(query));
var button = driver.FindElementByClassName("execute-button");
button?.Click();
driver.Manage()
.Timeouts()
.ImplicitWait = TimeSpan.FromSeconds(2);
// UGH!
result = driver
.FindElementByClassName("result-window").Text
.Replace("\n", "")
.Replace(" ", "");
});
// Assert
using var channelResponse = JsonDocument.Parse(result);
var data = channelResponse.RootElement.GetProperty("data");
data.GetProperty("hero").GetProperty("name").GetString().ShouldBe("R2-D2");
}
public async Task DisposeAsync()
{
await _host.StopAsync();
_host.Dispose();
}
internal class GraphiQlTestOptionsSetup : IConfigureOptions<GraphiQlOptions>
{
public void Configure(GraphiQlOptions options)
{
options.GraphiQlPath = Startup.CustomGraphQlPath;
}
}
}
}
================================================
FILE: tests/GraphiQl.Tests/SeleniumTest.cs
================================================
using System;
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
namespace GraphiQl.Tests
{
public abstract class SeleniumTest
{
private ChromeDriver Driver { get; }
protected bool RunHeadless { get; set; } = false;
protected SeleniumTest()
{
var options = new ChromeOptions();
options.AddArgument("--disable-dev-shm-usage");
options.AddArgument("--no-sandbox");
if (RunHeadless)
options.AddArgument("--headless");
Driver = new ChromeDriver(options);
}
protected void RunTest(Action<ChromeDriver> execute)
{
try
{
execute(Driver);
}
catch (Exception ex)
{
throw ex;
}
finally
{
Driver.Quit();
}
}
}
}
================================================
FILE: tests/GraphiQl.Tests/xunit.runner.json
================================================
{
"$schema": "https://xunit.net/schema/current/xunit.runner.schema.json",
"parallelizeTestCollections": false
}
gitextract_vo8n6p94/
├── .github/
│ └── workflows/
│ └── dotnetcore.yml
├── .gitignore
├── GraphiQl.sln
├── LICENSE
├── README.md
├── assets/
│ └── logo.psd
├── package.sh
├── src/
│ └── GraphiQl/
│ ├── AssetProvider.cs
│ ├── GraphiQl.csproj
│ ├── GraphiQlExtensions.cs
│ ├── GraphiQlMiddleware.cs
│ ├── GraphiQlOptions.cs
│ └── assets/
│ ├── graphiql.css
│ └── index.html
└── tests/
├── GraphiQl.Demo/
│ ├── .bowerrc
│ ├── Controllers/
│ │ └── GraphQlController.cs
│ ├── GraphQl/
│ │ ├── Droid.cs
│ │ ├── GraphQlQuery.cs
│ │ └── Models/
│ │ ├── DroidType.cs
│ │ └── StarWarsQuery.cs
│ ├── GraphiQl.Demo.csproj
│ ├── Program.cs
│ ├── Properties/
│ │ └── launchSettings.json
│ ├── Startup.cs
│ ├── appsettings.Development.json
│ └── appsettings.json
└── GraphiQl.Tests/
├── AuthenticationTest/
│ ├── ConfigureOptionsSetup.cs
│ └── DelegateSetup.cs
├── BasicTest.cs
├── Fixtures/
│ ├── GraphQlFixture.cs
│ └── HostFixture.cs
├── GraphiQl.Tests.csproj
├── OverrideGraphQlPathTests/
│ ├── ConfigureOptionsSetup.cs
│ └── DelegateSetup.cs
├── OverrideGraphiQlPathTests/
│ ├── ConfigureOptionsSetup.cs
│ └── DelegateSetup.cs
├── SeleniumTest.cs
└── xunit.runner.json
SYMBOL INDEX (99 symbols across 21 files)
FILE: src/GraphiQl/AssetProvider.cs
class AssetProvider (line 7) | internal class AssetProvider : IFileProvider
method AssetProvider (line 11) | public AssetProvider(EmbeddedFileProvider provider)
method GetFileInfo (line 14) | public IFileInfo GetFileInfo(string subpath)
method GetDirectoryContents (line 25) | public IDirectoryContents GetDirectoryContents(string subpath)
method Watch (line 28) | public IChangeToken Watch(string filter)
FILE: src/GraphiQl/GraphiQlExtensions.cs
class GraphiQlExtensions (line 13) | public static class GraphiQlExtensions
method AddGraphiQl (line 20) | public static IServiceCollection AddGraphiQl(this IServiceCollection s...
method UseGraphiQl (line 32) | public static IApplicationBuilder UseGraphiQl(this IApplicationBuilder...
method UseGraphiQl (line 35) | public static IApplicationBuilder UseGraphiQl(this IApplicationBuilder...
method UseGraphiQl (line 38) | public static IApplicationBuilder UseGraphiQl(this IApplicationBuilder...
method UseGraphiQlImp (line 41) | private static IApplicationBuilder UseGraphiQlImp(this IApplicationBui...
method WritePathJavaScript (line 69) | private static void WritePathJavaScript(IApplicationBuilder app, strin...
FILE: src/GraphiQl/GraphiQlMiddleware.cs
class GraphiQlMiddleware (line 8) | public class GraphiQlMiddleware
method GraphiQlMiddleware (line 13) | public GraphiQlMiddleware(RequestDelegate next, IOptions<GraphiQlOptio...
method Invoke (line 19) | public async Task Invoke(HttpContext context)
FILE: src/GraphiQl/GraphiQlOptions.cs
class GraphiQlOptions (line 8) | public class GraphiQlOptions
method GraphiQlOptions (line 16) | public GraphiQlOptions()
class GraphiQlOptionsSetup (line 23) | public class GraphiQlOptionsSetup : IConfigureOptions<GraphiQlOptions>
method Configure (line 25) | public void Configure(GraphiQlOptions options)
FILE: tests/GraphiQl.Demo/Controllers/GraphQlController.cs
class GraphQlController (line 10) | [Route(Startup.GraphQlPath)]
method Post (line 14) | [HttpPost]
FILE: tests/GraphiQl.Demo/GraphQl/Droid.cs
class Droid (line 3) | public class Droid
class Person (line 9) | public class Person
FILE: tests/GraphiQl.Demo/GraphQl/GraphQlQuery.cs
class GraphQlQuery (line 5) | public class GraphQlQuery
FILE: tests/GraphiQl.Demo/GraphQl/Models/DroidType.cs
class DroidType (line 5) | public class DroidType : ObjectGraphType<Droid>
method DroidType (line 7) | public DroidType()
class PersonType (line 14) | public class PersonType : ObjectGraphType<Person>
method PersonType (line 16) | public PersonType()
FILE: tests/GraphiQl.Demo/GraphQl/Models/StarWarsQuery.cs
class StarWarsQuery (line 5) | public class StarWarsQuery : ObjectGraphType
method StarWarsQuery (line 7) | public StarWarsQuery()
FILE: tests/GraphiQl.Demo/Program.cs
class Program (line 6) | public class Program
method Main (line 8) | public static void Main(string[] args)
method BuildWebHost (line 13) | public static IWebHost BuildWebHost(string[] args) =>
FILE: tests/GraphiQl.Demo/Startup.cs
class Startup (line 10) | public class Startup
method Startup (line 15) | public Startup(IConfiguration configuration)
method ConfigureGraphQl (line 22) | public virtual void ConfigureGraphQl(IServiceCollection services) {}
method ConfigureServices (line 24) | public void ConfigureServices(IServiceCollection services)
method Configure (line 35) | public void Configure(IApplicationBuilder app, IWebHostEnvironment env...
FILE: tests/GraphiQl.Tests/AuthenticationTest/ConfigureOptionsSetup.cs
class ConfigureOptionsSetup (line 15) | public class ConfigureOptionsSetup : SeleniumTest, IAsyncLifetime
method ConfigureOptionsSetup (line 19) | public ConfigureOptionsSetup()
method RequiresAuthentication (line 29) | [Fact]
method InitializeAsync (line 49) | public async Task InitializeAsync()
method DisposeAsync (line 52) | public Task DisposeAsync()
class GraphiQlTestOptionsSetup (line 58) | internal class GraphiQlTestOptionsSetup : IConfigureOptions<GraphiQlOp...
method Configure (line 60) | public void Configure(GraphiQlOptions options)
FILE: tests/GraphiQl.Tests/AuthenticationTest/DelegateSetup.cs
class CustomStartup (line 15) | public class CustomStartup : Startup
method CustomStartup (line 17) | public CustomStartup(IConfiguration configuration) : base(configuratio...
method ConfigureGraphQl (line 19) | public override void ConfigureGraphQl(IServiceCollection services)
class DelegateSetup (line 30) | public class DelegateSetup : SeleniumTest, IAsyncLifetime
method DelegateSetup (line 34) | public DelegateSetup()
method RequiresAuthentication (line 43) | [Fact]
method InitializeAsync (line 63) | public async Task InitializeAsync()
method DisposeAsync (line 66) | public Task DisposeAsync()
FILE: tests/GraphiQl.Tests/BasicTest.cs
class BasicTest (line 10) | public class BasicTest : SeleniumTest, IClassFixture<HostFixture>
method BasicTest (line 14) | public BasicTest(HostFixture fixture)
method CanQueryGraphQl (line 19) | [Fact]
FILE: tests/GraphiQl.Tests/Fixtures/GraphQlFixture.cs
class GraphQlFixture (line 15) | public class GraphQlFixture
method CreateHostBuilder (line 17) | public static IHostBuilder CreateHostBuilder(string[] args) =>
method CreateKestrel (line 26) | public async Task CreateKestrel()
method CreateWebHostOld (line 33) | public IWebHost CreateWebHostOld()
FILE: tests/GraphiQl.Tests/Fixtures/HostFixture.cs
class HostFixture (line 9) | public class HostFixture : IAsyncLifetime
method HostFixture (line 15) | public HostFixture()
method InitializeAsync (line 24) | public async Task InitializeAsync()
method DisposeAsync (line 27) | public async Task DisposeAsync()
FILE: tests/GraphiQl.Tests/OverrideGraphQlPathTests/ConfigureOptionsSetup.cs
class ConfigureOptionsSetup (line 15) | public class ConfigureOptionsSetup : SeleniumTest, IAsyncLifetime
method ConfigureOptionsSetup (line 19) | public ConfigureOptionsSetup()
method InitializeAsync (line 32) | public async Task InitializeAsync()
method CanOverrideGraphQlPath (line 35) | [Fact]
method DisposeAsync (line 73) | public async Task DisposeAsync()
class GraphiQlTestOptionsSetup (line 79) | internal class GraphiQlTestOptionsSetup : IConfigureOptions<GraphiQlOp...
method Configure (line 81) | public void Configure(GraphiQlOptions options)
FILE: tests/GraphiQl.Tests/OverrideGraphQlPathTests/DelegateSetup.cs
class CustomStartup (line 15) | public class CustomStartup : Startup
method CustomStartup (line 17) | public CustomStartup(IConfiguration configuration) : base(configuratio...
method ConfigureGraphQl (line 19) | public override void ConfigureGraphQl(IServiceCollection services)
class DelegateSetup (line 23) | public class DelegateSetup : SeleniumTest, IAsyncLifetime
method DelegateSetup (line 27) | public DelegateSetup()
method InitializeAsync (line 36) | public async Task InitializeAsync()
method CanOverrideGraphQlPath (line 39) | [Fact]
method DisposeAsync (line 71) | public async Task DisposeAsync()
FILE: tests/GraphiQl.Tests/OverrideGraphiQlPathTests/ConfigureOptionsSetup.cs
class ConfigureOptionsSetup (line 15) | public class ConfigureOptionsSetup : SeleniumTest, IAsyncLifetime
method ConfigureOptionsSetup (line 19) | public ConfigureOptionsSetup()
method InitializeAsync (line 32) | public async Task InitializeAsync()
method CanOverrideGraphiQlPath (line 35) | [Fact]
method DisposeAsync (line 67) | public async Task DisposeAsync()
class GraphiQlTestOptionsSetup (line 73) | internal class GraphiQlTestOptionsSetup : IConfigureOptions<GraphiQlOp...
method Configure (line 75) | public void Configure(GraphiQlOptions options)
FILE: tests/GraphiQl.Tests/OverrideGraphiQlPathTests/DelegateSetup.cs
class CustomStartup (line 16) | public class CustomStartup : Startup
method CustomStartup (line 18) | public CustomStartup(IConfiguration configuration) : base(configuratio...
method ConfigureGraphQl (line 20) | public override void ConfigureGraphQl(IServiceCollection services)
class DelegateSetup (line 24) | public class DelegateSetup : SeleniumTest, IAsyncLifetime
method DelegateSetup (line 28) | public DelegateSetup()
method InitializeAsync (line 37) | public async Task InitializeAsync()
method CanOverrideGraphiQlPath (line 40) | [Fact]
method DisposeAsync (line 74) | public async Task DisposeAsync()
class GraphiQlTestOptionsSetup (line 80) | internal class GraphiQlTestOptionsSetup : IConfigureOptions<GraphiQlOp...
method Configure (line 82) | public void Configure(GraphiQlOptions options)
FILE: tests/GraphiQl.Tests/SeleniumTest.cs
class SeleniumTest (line 7) | public abstract class SeleniumTest
method SeleniumTest (line 12) | protected SeleniumTest()
method RunTest (line 24) | protected void RunTest(Action<ChromeDriver> execute)
Condensed preview — 38 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (93K chars).
[
{
"path": ".github/workflows/dotnetcore.yml",
"chars": 787,
"preview": "name: .NET Core\n\non: [push, pull_request]\njobs:\n build:\n\n name: Github Actions Build\n # runs-on: ubuntu-latest\n "
},
{
"path": ".gitignore",
"chars": 2783,
"preview": "## Ignore Visual Studio temporary files, build results, and\n## files generated by popular Visual Studio add-ons.\n\n# User"
},
{
"path": "GraphiQl.sln",
"chars": 3936,
"preview": "\nMicrosoft Visual Studio Solution File, Format Version 12.00\n# Visual Studio 15\nVisualStudioVersion = 15.0.26124.0\nMini"
},
{
"path": "LICENSE",
"chars": 1072,
"preview": "MIT License\n\nCopyright (c) 2017 Joseph Woodward\n\nPermission is hereby granted, free of charge, to any person obtaining a"
},
{
"path": "README.md",
"chars": 3771,
"preview": "\n\n# GraphiQL.NET\n\n!["
},
{
"path": "package.sh",
"chars": 106,
"preview": "#!/usr/bin/env bash\n\nrm -rf ./package\ndotnet pack ./src/GraphiQl/GraphiQl.csproj -o ./package/ -c release"
},
{
"path": "src/GraphiQl/AssetProvider.cs",
"chars": 1004,
"preview": "using System;\nusing Microsoft.Extensions.FileProviders;\nusing Microsoft.Extensions.Primitives;\n\nnamespace GraphiQl\n{\n "
},
{
"path": "src/GraphiQl/GraphiQl.csproj",
"chars": 2662,
"preview": "<Project Sdk=\"Microsoft.NET.Sdk\">\n <PropertyGroup>\n <AssemblyName>GraphiQL</AssemblyName>\n <PackageId>GraphiQL</"
},
{
"path": "src/GraphiQl/GraphiQlExtensions.cs",
"chars": 2908,
"preview": "using System;\nusing System.Reflection;\nusing Microsoft.AspNetCore.Builder;\nusing Microsoft.AspNetCore.Http;\nusing Micro"
},
{
"path": "src/GraphiQl/GraphiQlMiddleware.cs",
"chars": 844,
"preview": "using System;\nusing System.Threading.Tasks;\nusing Microsoft.AspNetCore.Http;\nusing Microsoft.Extensions.Options;\n\nnamesp"
},
{
"path": "src/GraphiQl/GraphiQlOptions.cs",
"chars": 910,
"preview": "using System;\nusing System.Threading.Tasks;\nusing Microsoft.AspNetCore.Http;\nusing Microsoft.Extensions.Options;\n\nnamesp"
},
{
"path": "src/GraphiQl/assets/graphiql.css",
"chars": 36274,
"preview": ".graphiql-container,\n.graphiql-container button,\n.graphiql-container input {\n color: #141823;\n font-family:\n "
},
{
"path": "src/GraphiQl/assets/index.html",
"chars": 3638,
"preview": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"utf-8\" />\n <meta name=\"robots\" content=\"noindex\" />\n <meta na"
},
{
"path": "tests/GraphiQl.Demo/.bowerrc",
"chars": 33,
"preview": "{\n \"directory\": \"wwwroot/lib\"\n}\n"
},
{
"path": "tests/GraphiQl.Demo/Controllers/GraphQlController.cs",
"chars": 900,
"preview": "using System.Threading.Tasks;\nusing GraphiQl.Demo.GraphQl;\nusing GraphiQl.Demo.GraphQl.Models;\nusing GraphQL;\nusing Grap"
},
{
"path": "tests/GraphiQl.Demo/GraphQl/Droid.cs",
"chars": 299,
"preview": "namespace GraphiQl.Demo.GraphQl\n{\n public class Droid\n {\n public int Id { get; set; }\n public strin"
},
{
"path": "tests/GraphiQl.Demo/GraphQl/GraphQlQuery.cs",
"chars": 279,
"preview": "using GraphQL;\n\nnamespace GraphiQl.Demo.GraphQl\n{\n public class GraphQlQuery\n {\n public string OperationNa"
},
{
"path": "tests/GraphiQl.Demo/GraphQl/Models/DroidType.cs",
"chars": 824,
"preview": "using GraphQL.Types;\n\nnamespace GraphiQl.Demo.GraphQl.Models\n{\n public class DroidType : ObjectGraphType<Droid>\n "
},
{
"path": "tests/GraphiQl.Demo/GraphQl/Models/StarWarsQuery.cs",
"chars": 537,
"preview": "using GraphQL.Types;\n\nnamespace GraphiQl.Demo.GraphQl.Models\n{\n public class StarWarsQuery : ObjectGraphType\n {\n "
},
{
"path": "tests/GraphiQl.Demo/GraphiQl.Demo.csproj",
"chars": 417,
"preview": "<Project Sdk=\"Microsoft.NET.Sdk.Web\">\n <PropertyGroup>\n <TargetFramework>netcoreapp3.1</TargetFramework>\n </Proper"
},
{
"path": "tests/GraphiQl.Demo/Program.cs",
"chars": 411,
"preview": "using Microsoft.AspNetCore;\nusing Microsoft.AspNetCore.Hosting;\n\nnamespace GraphiQl.Demo\n{\n public class Program\n "
},
{
"path": "tests/GraphiQl.Demo/Properties/launchSettings.json",
"chars": 280,
"preview": "{\n \"profiles\": {\n \"GraphiQl.Demp\": {\n \"commandName\": \"Project\",\n \"launchBrowser\": true,\n \"launchUrl\":"
},
{
"path": "tests/GraphiQl.Demo/Startup.cs",
"chars": 1064,
"preview": "using Microsoft.AspNetCore.Builder;\nusing Microsoft.AspNetCore.Hosting;\nusing Microsoft.Extensions.Configuration;\nusing"
},
{
"path": "tests/GraphiQl.Demo/appsettings.Development.json",
"chars": 166,
"preview": "{\n \"Logging\": {\n \"IncludeScopes\": false,\n \"LogLevel\": {\n \"Default\": \"Debug\",\n \"System\": \"Information\","
},
{
"path": "tests/GraphiQl.Demo/appsettings.json",
"chars": 103,
"preview": "{\n \"Logging\": {\n \"IncludeScopes\": false,\n \"LogLevel\": {\n \"Default\": \"Warning\"\n }\n }\n}\n"
},
{
"path": "tests/GraphiQl.Tests/AuthenticationTest/ConfigureOptionsSetup.cs",
"chars": 2146,
"preview": "using System;\nusing System.Threading;\nusing System.Threading.Tasks;\nusing GraphiQl.Demo;\nusing Microsoft.AspNetCore;\nusi"
},
{
"path": "tests/GraphiQl.Tests/AuthenticationTest/DelegateSetup.cs",
"chars": 2035,
"preview": "using System;\nusing System.Threading;\nusing System.Threading.Tasks;\nusing GraphiQl.Demo;\nusing Microsoft.AspNetCore;\nusi"
},
{
"path": "tests/GraphiQl.Tests/BasicTest.cs",
"chars": 1466,
"preview": "using System;\nusing System.Text.Json;\nusing System.Threading;\nusing GraphiQl.Tests.Fixtures;\nusing Shouldly;\nusing Xunit"
},
{
"path": "tests/GraphiQl.Tests/Fixtures/GraphQlFixture.cs",
"chars": 1885,
"preview": "using System.Threading.Tasks;\nusing GraphiQl;\nusing GraphiQl.Demo;\nusing GraphiQl.Demo.Controllers;\nusing Microsoft.AspN"
},
{
"path": "tests/GraphiQl.Tests/Fixtures/HostFixture.cs",
"chars": 847,
"preview": "using System.Threading.Tasks;\nusing GraphiQl.Demo;\nusing Microsoft.AspNetCore;\nusing Microsoft.AspNetCore.Hosting;\nusing"
},
{
"path": "tests/GraphiQl.Tests/GraphiQl.Tests.csproj",
"chars": 1006,
"preview": "<Project Sdk=\"Microsoft.NET.Sdk.Web\">\n\n <PropertyGroup>\n <TargetFramework>netcoreapp3.1</TargetFramework>\n <IsPac"
},
{
"path": "tests/GraphiQl.Tests/OverrideGraphQlPathTests/ConfigureOptionsSetup.cs",
"chars": 2704,
"preview": "using System;\nusing System.Text.Json;\nusing System.Threading;\nusing System.Threading.Tasks;\nusing GraphiQl.Demo;\nusing M"
},
{
"path": "tests/GraphiQl.Tests/OverrideGraphQlPathTests/DelegateSetup.cs",
"chars": 2276,
"preview": "using System;\nusing System.Text.Json;\nusing System.Threading;\nusing System.Threading.Tasks;\nusing GraphiQl.Demo;\nusing M"
},
{
"path": "tests/GraphiQl.Tests/OverrideGraphiQlPathTests/ConfigureOptionsSetup.cs",
"chars": 2491,
"preview": "using System;\nusing System.Text.Json;\nusing System.Threading;\nusing System.Threading.Tasks;\nusing GraphiQl.Demo;\nusing M"
},
{
"path": "tests/GraphiQl.Tests/OverrideGraphiQlPathTests/DelegateSetup.cs",
"chars": 2680,
"preview": "using System;\nusing System.Text.Json;\nusing System.Threading;\nusing System.Threading.Tasks;\nusing GraphiQl.Demo;\nusing M"
},
{
"path": "tests/GraphiQl.Tests/SeleniumTest.cs",
"chars": 932,
"preview": "using System;\nusing OpenQA.Selenium;\nusing OpenQA.Selenium.Chrome;\n\nnamespace GraphiQl.Tests\n{\n public abstract class"
},
{
"path": "tests/GraphiQl.Tests/xunit.runner.json",
"chars": 115,
"preview": "{\n \"$schema\": \"https://xunit.net/schema/current/xunit.runner.schema.json\",\n \"parallelizeTestCollections\": false\n}"
}
]
// ... and 1 more files (download for full content)
About this extraction
This page contains the full source code of the JosephWoodward/graphiql-dotnet GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 38 files (84.6 KB), approximately 24.9k tokens, and a symbol index with 99 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.