diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..6b01847 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,40 @@ +name: Build Action + +on: + push: + paths: + - 'DataAccess/DataAccess.Repository/**' + - 'DataAccess/Extensions/DataAccess.Repository.HotChocolate/**' + +jobs: + + build: + + runs-on: ubuntu-latest + + strategy: + matrix: + project: ['DataAccess.Repository', 'DataAccess.Repository.HotChocolate'] + + steps: + - name: Checkout + uses: actions/checkout@v3 + + # Install the .NET Core workload + - name: Install .NET Core + uses: actions/setup-dotnet@v3 + with: + dotnet-version: 8.0.x + + # Set up local NuGet repo + - name: Setup GitHub NuGet + run: dotnet nuget add source --username USERNAME --password ${{ secrets.GITHUB_TOKEN }} --store-password-in-clear-text --name github "https://nuget.pkg.github.com/Ian-Webster/index.json" + + # Resource NuGet dependencies + - name: Restore dependencies + run: dotnet restore 'DataAccess/${{ matrix.project }}' + + # Build project + - name: Build + run: dotnet build --configuration Release 'DataAccess/${{ matrix.project }}' + diff --git a/DataAccess.Repository/DataAccess.Repository.csproj b/DataAccess.Repository/DataAccess.Repository.csproj index 43e7526..a3de38b 100644 --- a/DataAccess.Repository/DataAccess.Repository.csproj +++ b/DataAccess.Repository/DataAccess.Repository.csproj @@ -9,7 +9,7 @@ A simple base repository to be used in other projects requiring data access https://github.com/Ian-Webster/DataAccess https://github.com/Ian-Webster/DataAccess - 2.0.0-wip + 2.0.1 diff --git a/Extensions/DataAccess.Repository.HotChocolate/DataAccess.Repository.HotChocolate.csproj b/Extensions/DataAccess.Repository.HotChocolate/DataAccess.Repository.HotChocolate.csproj index b05a90d..9d2a8c9 100644 --- a/Extensions/DataAccess.Repository.HotChocolate/DataAccess.Repository.HotChocolate.csproj +++ b/Extensions/DataAccess.Repository.HotChocolate/DataAccess.Repository.HotChocolate.csproj @@ -4,6 +4,13 @@ net8.0 enable enable + True + DataAccess.HotChocolate + Extension to the DataAccess package adding GraphQL functionality via the HotChocolate library + https://github.com/Ian-Webster/DataAccess/Extensions/DataAccess.Repository.HotChocolate + https://github.com/Ian-Webster/DataAccess + 0.1.0 + diff --git a/Extensions/DataAccess.Repository.HotChocolate/readme.md b/Extensions/DataAccess.Repository.HotChocolate/readme.md index 4b49eb2..9995479 100644 --- a/Extensions/DataAccess.Repository.HotChocolate/readme.md +++ b/Extensions/DataAccess.Repository.HotChocolate/readme.md @@ -1,116 +1,117 @@ -# HotChocolate Extension -## Introduction -This extension provides GraphQL query functionality via the [HotChocolate Library](https://chillicream.com/docs/hotchocolate/v13) +# HotChocolate Extension +## Introduction +This extension provides GraphQL query functionality via the [HotChocolate Library](https://chillicream.com/docs/hotchocolate/v13) -## Installation -1. You'll need to install and set up the core data access NuGet package (see instructions [here](https://github.com/Ian-Webster/DataAccess#usage)) -2. Add the following NuGet packages to your IoC project; - 1. [HotChocolate](https://www.nuget.org/packages/HotChocolate/13.7.0?_src=template) - 2. [HotChocolate.AspNetCore](https://www.nuget.org/packages/HotChocolate.AspNetCore/13.7.0?_src=template) - 3. [HotChocolate.Data](https://www.nuget.org/packages/HotChocolate.Data/13.7.0?_src=template) -3. Add the following NuGet packages to your Repository project; - 1. [HotChocolate](https://www.nuget.org/packages/HotChocolate/13.7.0?_src=template) - 2. [HotChocolate.Data](https://www.nuget.org/packages/HotChocolate.Data/13.7.0?_src=template) - 3. TBC- this extension -4. Modify your IoC services to add and configure HotChocolate; - ```csharp - // set up HotChocolate - builder.Services.AddGraphQLServer() - .AddQueryType(q => q.Name("Query")) - .AddProjections() - .AddFiltering() - .AddSorting(); - ``` - 5.Modify your middleware configuration to include `app.MapGraphQL();` - 6. We'll revisit your IoC configuration later to add queries. +## Installation +1. You'll need to install and set up the core data access NuGet package (see instructions [here](https://github.com/Ian-Webster/DataAccess#usage)) +2. Add the following NuGet packages to your IoC project; + 1. [HotChocolate](https://www.nuget.org/packages/HotChocolate/13.7.0?_src=template) + 2. [HotChocolate.AspNetCore](https://www.nuget.org/packages/HotChocolate.AspNetCore/13.7.0?_src=template) + 3. [HotChocolate.Data](https://www.nuget.org/packages/HotChocolate.Data/13.7.0?_src=template) +3. Add the following NuGet packages to your Repository project; + 1. [HotChocolate](https://www.nuget.org/packages/HotChocolate/13.7.0?_src=template) + 2. [HotChocolate.Data](https://www.nuget.org/packages/HotChocolate.Data/13.7.0?_src=template) + 3. TBC- this extension +4. Modify your IoC services to add and configure HotChocolate; + ```csharp + // set up HotChocolate + builder.Services.AddGraphQLServer() + .AddQueryType(q => q.Name("Query")) + .AddProjections() + .AddFiltering() + .AddSorting(); + ``` + 5.Modify your middleware configuration to include `app.MapGraphQL();` + 6. We'll revisit your IoC configuration later to add queries. -## Building queries -Queries in GraphQL are like a stand-in for controller endpoints in REST, they provide a public API into your data, you can read more here https://chillicream.com/docs/hotchocolate/v13/defining-a-schema/queries +## Building queries +Queries in GraphQL are like a stand-in for controller endpoints in REST, they provide a public API into your data, you can read more here https://chillicream.com/docs/hotchocolate/v13/defining-a-schema/queries -HotChocolate can query your DBContext directly should you wish, however it does also provide a number of IQueryable extension methods and a query context class that allow you to use your own services and repository methods to perform the data operations. +HotChocolate can query your DBContext directly should you wish, however it does also provide a number of IQueryable extension methods and a query context class that allow you to use your own services and repository methods to perform the data operations. -The purpose of this extension library to obfuscate the complexities involved in modifying repository methods to support the HotChocolate extensions by providing a number of extension methods in the QueryExtensions; -* GetQueryItem - returns a single entity, supports filtering and projection -* GetQueryItems - returns a collection of entities, supports filtering, projection and sorting -* GetPagedQueryItems - returns a [Connection](https://chillicream.com/docs/hotchocolate/v13/fetching-data/pagination/#connections) object provided by the HotChocolate library, supports filtering, projection, sorting and pagination +The purpose of this extension library to obfuscate the complexities involved in modifying repository methods to support the HotChocolate extensions by providing a number of extension methods in the QueryExtensions; +* GetQueryItem - returns a single entity, supports filtering and projection +* GetQueryItems - returns a collection of entities, supports filtering, projection and sorting +* GetPagedQueryItems - returns a [Connection](https://chillicream.com/docs/hotchocolate/v13/fetching-data/pagination/#connections) object provided by the HotChocolate library, supports filtering, projection, sorting and pagination -Usage for this extension is as follows; -1. Modify your repository to accept IResolverContext and to call the extension, as an example this is how to get a single book entity for GraphQL; - ```csharp - // interface - using HotChocolate.Resolvers; // namespace for IResolverContext - namespace DataAccess.Example.Data.Repositories; - - public interface IBookRepository - { - Task GetBookForGraphQuery(IResolverContext context, CancellationToken token); - } +Usage for this extension is as follows; +1. Modify your repository to accept IResolverContext and to call the extension, as an example this is how to get a single book entity for GraphQL; + ```csharp + // interface + using HotChocolate.Resolvers; // namespace for IResolverContext + namespace DataAccess.Example.Data.Repositories; + + public interface IBookRepository + { + Task GetBookForGraphQuery(IResolverContext context, CancellationToken token); + } - // implementation - using DataAccess.Repository.HotChocolate; // namespace for this extension - using HotChocolate.Resolvers; // namespace for IResolverContext - - namespace DataAccess.Example.Data.Repositories; - - public class BookRepository: IBookRepository - { - private readonly IRepository _bookRepo; - - public BookRepository(RepositoryFactory repositoryFactory) - { - _bookRepo = repositoryFactory.GetRepositoryByType(); - } - - public async Task GetBookForGraphQuery(IResolverContext context, CancellationToken token) - { - return await _bookRepo.GetQueryItem(context, token); - } - } - ``` -2. Create a query class here is the book query; - ```csharp - using HotChocolate; - using HotChocolate.Types; - using HotChocolate.Resolvers; - - namespace DataAccess.Example.Data.Queries; - - [ExtendObjectType("Query")] - public class BookQuery - { - [UseProjection] // enable projecton for this query - [UseFiltering] // enable filtering for this query - // [Service] is an attribute hint provided by the HotChocolate library - // telling the code to use DI to retrieve the IBookRepository dependency - // IResolverContext and CancellationToken objects are provide as part of the - // GraphQL context - public async Task GetBook([Service] IBookRepository repository, IResolverContext context, CancellationToken token) - { - return await repository.GetBookForGraphQuery(context, token); - } - } - ``` -3. Modify the HotChocolate IoC configuration you added earlier to include your query; - ```csharp - // set up HotChocolate - builder.Services.AddGraphQLServer() - .AddQueryType(q => q.Name("Query")) - .AddTypeExtension() // adding the book query type - .AddProjections() - .AddFiltering() - .AddSorting(); - ``` -4. Run the API project as normal, you should be able to visit /graphql and see the [Banana Cake Pop](https://chillicream.com/products/bananacakepop/) UX -5. Run a query through the UX, as an example this will return the book "Fight Club" from the example project; - ```json - { - book (where: {bookId: {eq: "2c4a20f5-3fc8-4694-9c03-cb444bf416dc"}}) - { - bookId, - name - } - } - ``` + // implementation + using DataAccess.Repository.HotChocolate; // namespace for this extension + using HotChocolate.Resolvers; // namespace for IResolverContext + + namespace DataAccess.Example.Data.Repositories; + + public class BookRepository: IBookRepository + { + private readonly IRepository _bookRepo; + + public BookRepository(RepositoryFactory repositoryFactory) + { + _bookRepo = repositoryFactory.GetRepositoryByType(); + } + + public async Task GetBookForGraphQuery(IResolverContext context, CancellationToken token) + { + return await _bookRepo.GetQueryItem(context, token); + } + } + ``` +2. Create a query class here is the book query; + ```csharp + using HotChocolate; + using HotChocolate.Types; + using HotChocolate.Resolvers; + + namespace DataAccess.Example.Data.Queries; + + [ExtendObjectType("Query")] + public class BookQuery + { + [UseProjection] // enable projecton for this query + [UseFiltering] // enable filtering for this query + // [Service] is an attribute hint provided by the HotChocolate library + // telling the code to use DI to retrieve the IBookRepository dependency + // IResolverContext and CancellationToken objects are provide as part of the + // GraphQL context + public async Task GetBook([Service] IBookRepository repository, IResolverContext context, CancellationToken token) + { + return await repository.GetBookForGraphQuery(context, token); + } + } + ``` +3. Modify the HotChocolate IoC configuration you added earlier to include your query; + ```csharp + // set up HotChocolate + builder.Services.AddGraphQLServer() + .AddQueryType(q => q.Name("Query")) + .AddTypeExtension() // adding the book query type + .AddProjections() + .AddFiltering() + .AddSorting(); + ``` +4. Run the API project as normal, you should be able to visit /graphql and see the [Banana Cake Pop](https://chillicream.com/products/bananacakepop/) UX +5. Run a query through the UX, as an example this will return the book "Fight Club" from the example project; + ```json + { + book (where: {bookId: {eq: "2c4a20f5-3fc8-4694-9c03-cb444bf416dc"}}) + { + bookId, + name + } + } + ``` -## Version history -* 0.1.0 - Initial project creation, getting everything figured out and running locally +## Version history +* 1.0.0 - Initial release +* 0.1.0 - Initial project creation, getting everything figured out and running locally