Skip to content

Dynamically build TypeORM queries based on GraphQL queries for NestJS and TypeORM

License

Notifications You must be signed in to change notification settings

wesleyyoung/perch-query-builder

Repository files navigation


Logo

Perch Query Builder

Dynamically build TypeORM queries based on GraphQL queries for NestJS and TypeORM

Report Bug · Request Feature

Table of Contents
  1. About The Project
  2. Notes
  3. Getting Started
  4. Usage
  5. Roadmap
  6. Contributing
  7. License
  8. Contact

About The Project

In order to harness the true potential of NestJS, GraphQL, and TypeORM, I needed a way to dynamically fetch child relationships based on the GraphQL query coming in, without having to write a resolver specific to each entity and limited in depth. I went searching for a solution and found this thread. A solution had been posted by david-eos, but it wasn't functional enough to integrate easily into a proper NestJS + TypeORM + @nestjs/graphql project. I re-worked his solution into a portable and lightweight package generalizable enough to be used by anyone.

Built With

Getting Started

This plugin is light-weight and easy to install and use.

Installation

npm i --save perch-query-builder@latest

Usage

Use inside your resolver

import {Args, Context, Info, Query, Resolver} from '@nestjs/graphql';
import {Repository} from 'typeorm';
import {InjectRepository} from "@nestjs/typeorm";
import {PerchQueryBuilder} from 'perch-query-builder';
import {BookArgs} from '../args';
import {Book} from '../entities';

@Resolver(of => Book)
export class BookResolver {

    constructor(
        @InjectRepository(Book),
        private bookRepository: Repository<Book>,
    ) {}

    @Query(of => [Book], {
        name: `Book`,
        description: `Generic Collection Query For Books`,
        nullable: true,
    })
    async queryBooks(
        @Context() ctx,
        @Args() args: BookArgs,
        @Info() info: GraphQLResolveInfo,
    ): Promise<Book[]> {
        // Simply pass your entity's repository, and the GraphQLResolve Info
        return await PerchQueryBuilder.find<Book>(this.bookRepository, info);
    }
}

Sorting

In order to add the ability to sort results by a given property, import the OrderByArgs argument class and declare it as an argument in your resolver

option type description
_orderAscBy string Sorts the results as ascending from the value given
_orderDescBy string Sorts the results as descending from the value given
// rest of imports...
import {OrderByArgs} from "perch-query-builder";

// rest of resolver class...
    async queryBooks(
        @Context() ctx,
        @Args() args: BookArgs,
        // It is passed along side your other arguments
        @Args() orderByArgs: OrderByArgs,
        @Info() info: GraphQLResolveInfo,
    ): Promise<Book[]> {
        // There is nothing else to do, since OrderByArgs is only present to satisfy strict argument declaration requirements
        return await PerchQueryBuilder.find<Book>(this.bookRepository, info);
    }
// rest of resolver class...

Us in your query

{
    # Return Books sorted by title ascending
    Book(_orderAscBy: "title") {
        id
        title
    }
}

Pagination

Pagination is simple, though in a future feature "cursor" based pagination will be available as described in the GraphQL website

option type description
_limit integer Sets the max results to return, maps to the TypeORM SelectQueryBuilder<T>.take(number) method
_offset integer Sets the number of entities to skip before returning your query, maps to the TypeORM SelectQueryBuilder<T>.skip(number) method

In order to add pagination to your resolver, add the PaginationArgs argument class and declare it as an argument in your resolver

// rest of imports...
import {PaginationArgs} from "perch-query-builder";

// rest of resolver class...
    async queryBooks(
        @Context() ctx,
        @Args() args: BookArgs,
        // It is passed along side your other arguments
        @Args() paginationArgs: PaginationArgs,
        @Info() info: GraphQLResolveInfo,
    ): Promise<Book[]> {
        // There is nothing else to do, since PaginationArgs is only present to satisfy strict argument declaration requirements
        return await PerchQueryBuilder.find<Book>(this.bookRepository, info);
    }
// rest of resolver class...

Us in your query

{
    # Return only 5 Books starting from the 10th book
    Book(_limit: 5, _offset: 10) {
        id
        title
    }
}

Roadmap

See the open issues for a list of proposed features (and known issues).

Contributing

Contributions are what make the open source community such an amazing place to be learn, inspire, and create. Any contributions you make are greatly appreciated.

  1. Fork the Project
  2. Create your Feature Branch (git checkout -b feature/AmazingFeature)
  3. Commit your Changes (git commit -m 'Add some AmazingFeature')
  4. Push to the Branch (git push origin feature/AmazingFeature)
  5. Open a Pull Request.

Acknowledgements

Credit to david-eos for writing the base functionality.

License

Distributed under the MIT License.

Contact

Wesley Young - @FullstackAttack - [email protected]

Project Link: https://github.com/wesleyyoung/perch-query-builder

About

Dynamically build TypeORM queries based on GraphQL queries for NestJS and TypeORM

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 3

  •  
  •  
  •