Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/Shane32/GraphQL.DI
Browse files Browse the repository at this point in the history
  • Loading branch information
Shane32 committed Jul 2, 2021
2 parents 788bd38 + 6d84b62 commit 6640ec5
Show file tree
Hide file tree
Showing 64 changed files with 40,577 additions and 1 deletion.
8 changes: 7 additions & 1 deletion GraphQL.DI.sln
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution items", "Solution
README.md = README.md
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tests", "src\Tests\Tests.csproj", "{BA5F3790-9FE0-4A10-8528-0756334AC727}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tests", "src\Tests\Tests.csproj", "{BA5F3790-9FE0-4A10-8528-0756334AC727}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sample", "Sample\Sample.csproj", "{4AB70777-E140-49E4-8173-7809DF67A021}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand All @@ -32,6 +34,10 @@ Global
{BA5F3790-9FE0-4A10-8528-0756334AC727}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BA5F3790-9FE0-4A10-8528-0756334AC727}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BA5F3790-9FE0-4A10-8528-0756334AC727}.Release|Any CPU.Build.0 = Release|Any CPU
{4AB70777-E140-49E4-8173-7809DF67A021}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4AB70777-E140-49E4-8173-7809DF67A021}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4AB70777-E140-49E4-8173-7809DF67A021}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4AB70777-E140-49E4-8173-7809DF67A021}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
27 changes: 27 additions & 0 deletions Sample/DataLoaders/PersonDataLoader.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using GraphQL.DataLoader;
using Microsoft.EntityFrameworkCore;
using Sample.DbModels;

namespace Sample.DataLoaders
{
public class PersonDataLoader : DataLoaderBase<int, Person>
{
private TodoDbContext _db;
public PersonDataLoader(TodoDbContext db) => _db = db;

protected override async Task FetchAsync(IEnumerable<DataLoaderPair<int, Person>> list, CancellationToken cancellationToken)
{
var ids = list.Select(x => x.Key);
var people = await _db.Set<Person>().Where(x => ids.Contains(x.Id)).ToDictionaryAsync(x => x.Id, cancellationToken);
foreach (var value in list) {
people.TryGetValue(value.Key, out var person);
value.SetResult(person);
}
}
}
}
13 changes: 13 additions & 0 deletions Sample/DbModels/Person.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Sample.DbModels
{
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
}
}
20 changes: 20 additions & 0 deletions Sample/DbModels/Todo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Threading.Tasks;

namespace Sample.DbModels
{
public class Todo
{
public int Id { get; set; }
public string Title { get; set; }
public string Notes { get; set; }
public bool Completed { get; set; }
public DateTime? CompletionDate { get; set; }
public int? CompletedByPersonId { get; set; }
[ForeignKey("CompletedByPersonId")]
public Person CompletedBy { get; set; }
}
}
16 changes: 16 additions & 0 deletions Sample/DoNotMapClrTypeAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Sample
{
/// <summary>
/// Indicates that GetClrTypeMappings should
/// skip this class when scanning an assembly for CLR type mappings.
/// </summary>
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
public class DoNotMapClrTypeAttribute : Attribute
{
}
}
55 changes: 55 additions & 0 deletions Sample/GraphTypes/MutationType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using GraphQL.Types;
using GraphQL.DI;
using Sample.DbModels;
using Microsoft.EntityFrameworkCore;
using GraphQL;
using System.Threading;

namespace Sample.GraphTypes
{
public class MutationType : DIObjectGraphType<Mutation> { }
public class Mutation : DIObjectGraphBase<object>
{
public readonly TodoDbContext _db;
public Mutation(TodoDbContext db) => _db = db;

public async Task<Todo> AddTodoAsync([Required] string title, string notes, CancellationToken cancellationToken)
{
var todo = new Todo {
Title = title,
Notes = notes,
};
_db.Add(todo);
await _db.SaveChangesAsync(cancellationToken);
return todo;
}

public async Task<bool> DeleteTodoAsync(int id, CancellationToken cancellationToken)
{
var todo = await _db.Set<Todo>().Where(x => x.Id == id).SingleOrDefaultAsync();
if (todo == null)
return false;
_db.Set<Todo>().Remove(todo);
await _db.SaveChangesAsync(cancellationToken);
return true;
}

public async Task<Todo> SetCompleteAsync(int id, int completedByPersonId, CancellationToken cancellationToken)
{
var todo = await _db.Set<Todo>().Where(x => x.Id == id).SingleOrDefaultAsync(cancellationToken);
if (todo == null)
return null;
if (todo.Completed)
throw new ExecutionError($"Task id {id} has already been completed");
todo.Completed = true;
todo.CompletedByPersonId = completedByPersonId;
todo.CompletionDate = DateTime.Now;
await _db.SaveChangesAsync(cancellationToken);
return todo;
}
}
}
18 changes: 18 additions & 0 deletions Sample/GraphTypes/PersonType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using GraphQL.Types;
using Sample.DbModels;

namespace Sample.GraphTypes
{
public class PersonType : ObjectGraphType<Person>
{
public PersonType()
{
Field(x => x.Id);
Field(x => x.Name);
}
}
}
40 changes: 40 additions & 0 deletions Sample/GraphTypes/QueryType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using GraphQL.Types;
using GraphQL.DI;
using Sample.DbModels;
using Microsoft.EntityFrameworkCore;
using System.Threading;

namespace Sample.GraphTypes
{
public class QueryType : DIObjectGraphType<Query> { }
public class Query : DIObjectGraphBase<object>
{
private readonly TodoDbContext _db;
public Query(TodoDbContext db)
{
_db = db;
}

public async Task<IEnumerable<Todo>> TodosAsync(int? id, IEnumerable<int> ids, int? completedByPersonId, CancellationToken cancellationToken)
{
IQueryable<Todo> query = _db.Set<Todo>();
if (id.HasValue)
query = query.Where(x => x.Id == id);
if (ids != null)
query = query.Where(x => ids.Contains(x.Id));
if (completedByPersonId != null)
query = query.Where(x => x.CompletedByPersonId == completedByPersonId);

return await query.ToListAsync(cancellationToken);
}

public async Task<Todo> TodoAsync(int id, CancellationToken cancellationToken)
{
return await _db.Set<Todo>().Where(x => x.Id == id).SingleOrDefaultAsync(cancellationToken);
}
}
}
42 changes: 42 additions & 0 deletions Sample/GraphTypes/TodoType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using GraphQL.DataLoader;
using GraphQL.DI;
using Sample.DataLoaders;
using Sample.DbModels;

namespace Sample.GraphTypes
{
public class TodoType : DIObjectGraphType<TodoObjType, Todo>
{
// mix and match if you like
public TodoType()
{
// some properties defined traditionally
Field(x => x.Id);
Field(x => x.Title);
Field(x => x.Notes, true);
}
}

public class TodoObjType : DIObjectGraphBase<Todo>
{
private readonly PersonDataLoader _personDataLoader;
public TodoObjType(PersonDataLoader personDataLoader) => _personDataLoader = personDataLoader;

// some properties defined here
// use 'static' and it won't create a dbcontext
public static bool Completed(Todo source) => source.Completed;
public static DateTime? CompletedOn(Todo source) => source.CompletionDate;

public IDataLoaderResult<Person> CompletedBy(Todo source)
{
if (!source.CompletedByPersonId.HasValue)
return null;

return _personDataLoader.LoadAsync(source.CompletedByPersonId.Value);
}
}
}
26 changes: 26 additions & 0 deletions Sample/Pages/Error.cshtml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
@page
@model ErrorModel
@{
ViewData["Title"] = "Error";
}

<h1 class="text-danger">Error.</h1>
<h2 class="text-danger">An error occurred while processing your request.</h2>

@if (Model.ShowRequestId)
{
<p>
<strong>Request ID:</strong> <code>@Model.RequestId</code>
</p>
}

<h3>Development Mode</h3>
<p>
Swapping to the <strong>Development</strong> environment displays detailed information about the error that occurred.
</p>
<p>
<strong>The Development environment shouldn't be enabled for deployed applications.</strong>
It can result in displaying sensitive information from exceptions to end users.
For local debugging, enable the <strong>Development</strong> environment by setting the <strong>ASPNETCORE_ENVIRONMENT</strong> environment variable to <strong>Development</strong>
and restarting the app.
</p>
32 changes: 32 additions & 0 deletions Sample/Pages/Error.cshtml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;

namespace Sample.Pages
{
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
[IgnoreAntiforgeryToken]
public class ErrorModel : PageModel
{
public string RequestId { get; set; }

public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);

private readonly ILogger<ErrorModel> _logger;

public ErrorModel(ILogger<ErrorModel> logger)
{
_logger = logger;
}

public void OnGet()
{
RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier;
}
}
}
12 changes: 12 additions & 0 deletions Sample/Pages/Index.cshtml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
@page
@model IndexModel
@{
ViewData["Title"] = "Home page";
}

<div class="text-center">
<h1 class="display-4">Welcome</h1>
<p>Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p>
</div>

<a href="/ui/graphiql">GraphiQL</a>
25 changes: 25 additions & 0 deletions Sample/Pages/Index.cshtml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Sample.Pages
{
public class IndexModel : PageModel
{
private readonly ILogger<IndexModel> _logger;

public IndexModel(ILogger<IndexModel> logger)
{
_logger = logger;
}

public void OnGet()
{

}
}
}
8 changes: 8 additions & 0 deletions Sample/Pages/Privacy.cshtml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
@page
@model PrivacyModel
@{
ViewData["Title"] = "Privacy Policy";
}
<h1>@ViewData["Title"]</h1>

<p>Use this page to detail your site's privacy policy.</p>
24 changes: 24 additions & 0 deletions Sample/Pages/Privacy.cshtml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Sample.Pages
{
public class PrivacyModel : PageModel
{
private readonly ILogger<PrivacyModel> _logger;

public PrivacyModel(ILogger<PrivacyModel> logger)
{
_logger = logger;
}

public void OnGet()
{
}
}
}
Loading

0 comments on commit 6640ec5

Please sign in to comment.