Code Monkey home page Code Monkey logo

type-graphql's Introduction

logo

TypeGraphQL

release website codeql discord codecov npm open collective

Create GraphQL schema and resolvers with TypeScript, using classes and decorators!

https://typegraphql.com

donate

Introduction

TypeGraphQL makes developing GraphQL APIs an enjoyable process, i.e. by defining the schema using only classes and a bit of decorator magic.

So, to create types like object type or input type, we use a kind of DTO class. For example, to declare Recipe type we simply create a class and annotate it with decorators:

@ObjectType()
class Recipe {
  @Field(type => ID)
  id: string;

  @Field()
  title: string;

  @Field(type => [Rate])
  ratings: Rate[];

  @Field({ nullable: true })
  averageRating?: number;
}

And we get the corresponding part of the schema in SDL:

type Recipe {
  id: ID!
  title: String!
  ratings: [Rate!]!
  averageRating: Float
}

Then we can create queries, mutations and field resolvers. For this purpose, we use controller-like classes that are called "resolvers" by convention. We can also use awesome features like dependency injection and auth guards:

@Resolver(Recipe)
class RecipeResolver {
  // dependency injection
  constructor(private recipeService: RecipeService) {}

  @Query(returns => [Recipe])
  recipes() {
    return this.recipeService.findAll();
  }

  @Mutation()
  @Authorized(Roles.Admin) // auth guard
  removeRecipe(@Arg("id") id: string): boolean {
    return this.recipeService.removeById(id);
  }

  @FieldResolver()
  averageRating(@Root() recipe: Recipe) {
    return recipe.ratings.reduce((a, b) => a + b, 0) / recipe.ratings.length;
  }
}

And in this simple way, we get this part of the schema in SDL:

type Query {
  recipes: [Recipe!]!
}

type Mutation {
  removeRecipe(id: String!): Boolean!
}

Motivation

We all know that GraphQL is great and solves many problems we have with REST APIs, like Over-Fetching and Under-Fetching. But developing a GraphQL API in Node.js with TypeScript is sometimes a bit of a pain. Why? Let's take a look at the steps we usually have to take.

First, we create all the GraphQL types in schema.graphql using SDL. Then we create our data models using ORM classes, which represent our DB entities. Then we start to write resolvers for our queries, mutations and fields, but this forces us to first create TS interfaces for all arguments, inputs, and even object types.

Only then can we implement the resolvers using weird generic signatures and manually performing common tasks, like validation, authorization and loading dependencies:

export const getRecipesResolver: GraphQLFieldResolver<void, Context, GetRecipesArgs> = async (
  _,
  args,
  ctx,
) => {
  // common tasks repeatable for almost every resolver
  const repository = TypeORM.getRepository(Recipe);
  const auth = Container.get(AuthService);
  await joi.validate(getRecipesSchema, args);
  if (!auth.check(ctx.user)) {
    throw new NotAuthorizedError();
  }

  // our business logic, e.g.:
  return repository.find({ skip: args.offset, take: args.limit });
};

The biggest problem is redundancy in our codebase, which makes it difficult to keep things in sync. To add a new field to our entity, we have to jump through all the files - modify an entity class, the schema, as well as the interface. The same goes for inputs or arguments. It's easy to forget to update one piece or make a mistake with a single type. Also, what if we've made a typo in the field name? The rename feature (F2) won't work correctly.

Tools like GraphQL Code Generator or graphqlgen only solve the first part - they generate the corresponding interfaces (and resolvers skeletons) for our GraphQL schema but they don't fix the schema <--> models redundancy and developer experience (F2 rename won't work, you have to remember about the codegen watch task in the background, etc.), as well as common tasks like validation, authorization, etc.

TypeGraphQL comes to address these issues, based on experience from a few years of developing GraphQL APIs in TypeScript. The main idea is to have only one source of truth by defining the schema using classes and some help from decorators. Additional features like dependency injection, validation and auth guards help with common tasks that normally we would have to handle ourselves.

Documentation

The documentation, installation guide, and detailed description of the API and all of its features are available on the website.

Getting started

A full getting started guide with a simple walkthrough (tutorial) can be found at getting started docs.

Video tutorial

If you prefer video tutorials, you can watch Ben Awad's TypeGraphQL video series on YouTube.

Examples

You can also check the examples folder in this repository for more examples of usage: simple fields resolvers, DI Container support, TypeORM integration, automatic validation, etc.

The Tests folder might also give you some tips on how to get various things done.

Security contact information

To report a security vulnerability, please use the Tidelift security contact. Tidelift will coordinate the fix and disclosure.

The future

The currently released version is a stable 1.0.0 release. It is well-tested (97% coverage, ~500 test cases) and has most of the planned features already implemented. Plenty of companies and independent developers are using it in production with success.

However, there are also plans for a lot more features like better TypeORM, Prisma and DataLoader integration, custom decorators and metadata annotations support - the full list of ideas is available on the GitHub repo. You can also keep track of development's progress on the project board.

If you have any interesting feature requests, feel free to open an issue on GitHub so we can discuss that!

Support

TypeGraphQL is an MIT-licensed open-source project. This framework is a result of the tremendous amount of work - sleepless nights, busy evenings and weekends.

It doesn't have a large company that sits behind it - its ongoing development is possible only thanks to the support of the community.

donate

Gold Sponsors ๐Ÿ†

Please ask your company to support this open source project by becoming a gold sponsor and getting a premium technical support from our core contributors.

Silver Sponsors ๐Ÿฅˆ

Please ask your company to support this open source project by becoming a silver sponsor.

Bronze Sponsors ๐Ÿฅ‰

live graphic systems lifeX aps instinctools vps server
Live Graphic Systems LifeX Aps instinctools VPS Server
NonGamstopBets CasinoDeps.co.nz Non Stop Casino
NonGamstopBets CasinoDeps Non Stop Casino

become a sponsor

Members ๐Ÿ’ช

Members

GitHub Sponsors

GitHub Sponsors

Community

Want to help?

Want to file a bug, contribute some code, or improve the documentation? Great! Please read our guidelines for CONTRIBUTING and then check out one of our help-wanted issues.

type-graphql's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

type-graphql's Issues

Advanced enum support

Support for enums with descriptions and depreciations.

API Draft

@EnumType({ description: "All posible directions of moves the on grid" })
class DirectionEnumType {
  @EnumValue({ description: "Up to the sky!" })
  Up: string;

  @EnumValue()
  Down: string;

  @EnumValue({ deprecationReason: "Use `Down` instead" })
  Bottom = this.Down;

  @EnumValue() 
  Left: string;

  @EnumValue() 
  Right: string;
}

// we don't use `DirectionEnumType` class on runtime, so only export "real" enum `Direction`
export const Direction = createEnum(DirectionEnumType);


// usage in definitions
@ObjectType()
class Movement {
  @Field(type => Direction)
  direction: Enum<typeof Direction>;
}

// usage in resolvers
const mov = new Movement();
mov.direction = Direction.Right;
mov.direction = "Left";

switch (mov.direction) {
  case Direction.Right:
    console.log("right!");
    break;
  case Direction.Left:
    console.log("left!");
    break;
  // etc.
}

Bug: value.toISOString is not a function

I am getting following error when quering for an object with an iso date field:

serialize(value: Date) {
  return value.toISOString();
},
// date type gets lost on transpile and leads to this error
serialize(value) {
  return value.toISOString();
},

tsconfig min target

It would appear that there are requirements of type-graphql which requires a target higher than I had originally been using. My project was stuck at es5, and resolvers for non-scalar types where not being called. Only after bumping that up to es6 or higher seemed to resolve this issue.

Along with the other tsconfig file suggestions, it may be helpful to specify what the min target language is.

Proposal: Add support for extends

Please add support for object extension.

@GraphQLObjectType()
abstract class B {
    @Field()
    b: string;
}

@GraphQLObjectType()
abstract class A extends B {
    @Field()
    a: string;
}


@GraphQLResolver(() => TestResolver)
class TestResolver {

    @Query(returnType => A, {description: ''})
    test() {
        return {
            a: 'a-value',
            b: 'b-value'
        };
    }
}

Expected result:

{"data":{"test":{"a":"a-value","b":"b-value"}}}

Actual result:

{"errors":[{"message":"Cannot query field \"b\" on type \"A\". Did you mean \"a\"?","locations":[{"line":1,"column":9}]}]}

Feature: Data loader integration

https://github.com/facebook/dataloader

  1. Caching resolving the same data
  2. Instead of normal resolving:
@FieldResolver()
author(@Root() recipe: Recipe) {
  return this.userRepository.findById(recipe.authorId);
}

Introduce batched resolving - taking array of roots:

@FieldResolver()
async author(@Root() recipes: Recipe[]) {
  const ids = recipes.map(r => r.authorId);
  return this.userRepository.findByIds(ids);
}
  1. Decorator:
@Mutation()
async mutationThatAffectLoader(
  @Arg("input") input: SomeInput,
  @DataLoader(User) loader,
) {
  const result = await this.mutateSomething(input);
  loader.clear(input.someKey);
  return result;
}

Default values in schema

I want optional args that have default values defined in GraphQL (not just nullable types with default variable values). Is this possible?

Custom decorators support

To improve decoupling the business logic from framework/graphql stuffs (resolvers as services), TypeGraphQL should allow to register param decorators to extract some data from context, root/source, etc. It could be for example @CurrentUser decorator:

const CurrentUser = createParamDecorator(({ context }) => context.user);

class SampleResolver {
  @Mutation()
  rate(@CurrentUser() user: User, @Arg("rate") rate: RateEnum) {
    this.ratingsService.addRate({ user, rate });
  }
}

Also it should be possible to create field/method decorators to provide some metadata or capture requests, eg. @CacheControl:

class SampleResolver {
  @Query()
  @CacheControl(5000)
  sampleQuery(): boolean {
    // will be called at most once per 5s
    return this.database.performCostlyOperation();
  }
}

This feature would be a syntax sugar over middlewares (#14) feature.

Test coverage

Features

  • descriptions
  • depreciations
  • custom scalars
  • validation
  • IoC container
  • basic schema generation (decorators options)
  • resolvers (getter, method, this, class resolvers, args, etc.)

Others

  • Create unit tests for helper functions doesn't covered with functional tests

TypeORM integration plugin

I wonder whether TypeGraphQL should stay as the uniwersal framework that works with many libs or to be more integrated with the libs that the most of the devs would use, like TypeORM.

I am thinking about the automatic relations resolving feature that could use lazy relation wrapper mechanizm or typeorm-loader for performance purposes.

The best way would be to create plugin system and create @typegraphql/typeorm helper package that would provide better integration. I have to investigate this way if it's possible.

Any ideas, guys โ“

Base Query/Mutations

I was actually working on implementing something similar to this:

https://github.com/j/graphql-party

I just had a complete re-write that I was going to try to push later which has most of the features here, until I saw this library. The code-base is clean and concise and exciting! So good job.

One question that I made sure to implement with my project. Most of my projects have common Query / Mutation functionality. Do you have a query/mutation plugin system or resolver inheritance with the ability to rename fields?

i.e.

// RecipeResolver.ts
@Resolver(objectType => Recipe)
@Use(Deletable, Updatable, Findable)
class RecipeResolver {
  // ...
  @Query(() => Recipe, { array: true })
  favoriteRecipes(): Promise<Array<Recipe>> {
    return this.recipeRepository.findFavorites();
  }
}

// Deletable.ts
function Deletable(name) {
  return class Deletable {
    @Mutation(returnType => Boolean)
    async [`delete${name}`]() {
      // implementation...
    }
  }
]

// Updateable.ts
// ... implementaiton...

// Findable.ts
// ... implementaiton...


// Creates schema:

/*

type Query {
  favoriteRecipes: [Recipe]
  deleteRecipe: Boolean
  Recipe: Recipe
  allRecipes: [Recipe]
}

type Mutation {
  deleteRecipe: Boolean
  updateRecipe: Recipe
}

*/

Thanks!

Not assignable to type 'Promise<OptionsData>

ts-node --type-check ./examples/simple-usage/index.ts                 

/Users/jas/.config/yarn/global/node_modules/ts-node/src/index.ts:327
        throw new TSError(formatDiagnostics(diagnosticList, cwd, ts, lineOffset))
              ^
TSError: โจฏ Unable to compile TypeScript
examples/simple-usage/index.ts (18,17): Argument of type '{ schema: GraphQLSchema; graphiql: true; }' is not assignable to parameter of type 'Options'.
  Type '{ schema: GraphQLSchema; graphiql: true; }' is not assignable to type 'Promise<OptionsData>'.
    Property 'then' is missing in type '{ schema: GraphQLSchema; graphiql: true; }'. (2345)
    at getOutput (/Users/jas/.config/yarn/global/node_modules/ts-node/src/index.ts:327:15)
    at Object.compile (/Users/jas/.config/yarn/global/node_modules/ts-node/src/index.ts:513:11)
    at Module.m._compile (/Users/jas/.config/yarn/global/node_modules/ts-node/src/index.ts:400:43)
    at Module._extensions..js (module.js:660:10)
    at Object.require.extensions.(anonymous function) [as .ts] (/Users/jas/.config/yarn/global/node_modules/ts-node/src/index.ts:403:12)
    at Module.load (module.js:561:32)
    at tryModuleLoad (module.js:501:12)
    at Function.Module._load (module.js:493:3)
    at Function.Module.runMain (module.js:690:10)
    at Object.<anonymous> (/Users/jas/.config/yarn/global/node_modules/ts-node/src/bin.ts:141:12)

Validate Query 's ArgType?

The document shows examples of validating @InputType(), but is it possible to validate the arguments for a query? I've tried the following but ArrayMaxSize is ignored. In the following case, I want to validate the ids arguments:

import {ArrayMaxSize} from "class-validator";

@ArgsType()
class FindMultipleItemsArgs {
    @ArrayMaxSize(2)
    @Field(type => [ID])
    ids: number[];
}

@Resolver(objectType => Recipe)
export class ItemResolver {

    public constructor(
        @OrmRepository(ItemInfo) private repository: Repository<ItemInfo>,
    ){}

    @Query(returnType => [ItemInfo], { array: true })
    async itemList(@Args() {ids}: FindMultipleItemsArgs): Promise<ItemInfo[] | undefined> {
        return this.repository.findByIds(ids);
    }
}
    const schema = await buildSchema({
        resolvers: [ '../resolver/*.js'],
        validate: true
    });

API reference with JSDocs

  • create JSDoc for all decorators and public interfaces/functions/etc.
  • create docs section with API Reference (text from JSDoc, samples from item signature)
  • investigate usage of TypeDoc
  • configure website to show API reference

Continous integration

  • prepare ts-lint task 0ad0135
  • prepare tsc (type-check) task 0ad0135
  • create git hooks for running checks on push
  • configure travis to run this tasks on every commit/PR
  • reconfigure travis when unit tests are introduced #15

TypeError: Reflect.getMetadata is not a function

Hi there ๐Ÿ‘‹
I've posted this question on the apollo slack #general and after looking up and testing all projects related to this on github I finally stumble upon this amazing project. I am very hopeful on this one.

Our project have a lot of types definitions written in typescript as interfaces, so reusing them would be a great benefit in terms of time, reusability, type safety ,stability and greatness :)

So thank you for maintaining this ๐Ÿ‘
Still, I am having a hard time trying to get a minimal viable example working.

"dependencies": {
  "reflect-metadata": "^0.1.12",
  "type-graphql": "^0.1.2"
}
// example.ts
import {Field, GraphQLObjectType, ID} from 'type-graphql';

@GraphQLObjectType()
class Recipe {
    @Field(type => ID)
    readonly id: string;

    @Field()
    title: string;

    @Field({nullable: true})
    description?: string;

    @Field({nullable: true})
    averageRating?: number;
}
// test.ts
import {buildSchema} from 'type-graphql';
import {Recipe} from './example';

function test() {
    const schema = buildSchema({
        resolvers: [Recipe],
    });
    console.log(schema);
}

test();
ts-node -O '{"module": "commonjs"}' test.ts
[..]\node_modules\type-graphql\helpers\findType.js:7
    const reflectedType = Reflect.getMetadata(metadataKey, prototype.constructor.prototype, propertyKey);
                                  ^
TypeError: Reflect.getMetadata is not a function
    at Object.findType ([..]\node_modules\type-graphql\helpers\findType.js:7:35)
    at Field ([..]\node_modules\type-graphql\decorators\Field.js:14:53)
    at __decorate ([..]\src\main\ts\models\example\example.js:5:110)
    at Object.<anonymous> ([..]\src\main\ts\models\example\example.ts:6:5)
    at Module._compile (module.js:660:30)
    at Object.Module._extensions..js (module.js:671:10)
    at Module.load (module.js:573:32)
    at tryModuleLoad (module.js:513:12)
    at Function.Module._load (module.js:505:3)
    at Module.require (module.js:604:17)

Any help would be much appreciated.

Synchronous version of buildSchema

Hello,

Nice project!

buildSchema currently only returns promises.

For my uses case, this is a problem because I'm writing Firebase functions, which are supposed to export something from the module: export const api: firebaseFunctions.HttpsFunction = firebaseFunctions.https.onRequest(app);, where "app" is an "express" app in which I'm using Apollo GraphQL, which.. needs the GraphQL schema.

For this reason I can't apply your approach with an async ``bootstrap` function..

I don't find an easy work around for this issue; do you have any ideas or think a synchronous version of the "buildSchema" function could be added?

Authorization layer

@Authenticated decorator with authChecker logic

  • register roles in metadatas
  • create auth checker support
  • guards on resolvers
  • guards on fields
  • tests for schema/reflection, errors and functional
  • examples of usage
  • docs about this feature

Custom scalars support

  • registering and implementing own scalars
  • ability to map class properties types to scalars (eg. Date)

Is there anyway to call a resolver from another resolver

Is there any way to fetch data from another resolver without using graphql?
For example:

@Resolver()
class ItemResolver{
    item(@Args(){id}:SomeArgs){
          return {someData:[]}
     }
}

@Resolver()
class BrandResolver{
     async brand(@Args(){brandId}:SomeArgs){
            let data = await ItemResolver.item({5})
     }
}

Website

Nice website

Prepare the website with:

  • tutorials/getting started
  • advanced usage guides
  • FAQ

It should support embedding markdown from docs on github repo.
Docusaurus should be a good solution.
Github.io would be a good hosting at the beginning.

Fields decorator to inject parsed AST info

Some people instead of batching and caching separate resolvers (#51) prefer to load all the data manually. So when they resolve the query, they parse the resolve info object to get a list/structure of fields to fetch from DB or API and then create specific query to DB/API.

Also it might be useful for selecting fields/columns from DB, e.g. when the GraphQL query requires only a single field but our database SQL query has to be universal so it has * so it returns a lot of unnecessary data, like other 30 columns/fields.

It would be nice to have a decorator for that with nice integration with graphql-fields. It should convert the returned object to a mongo-like convention (robrichard/graphql-fields#5) and have an ability to return array of keys in first level (without nesting) for sql queries optimization.

It should also take care about mapping the GraphQL field names (provided with { name: "fieldName" } option) to the TS property names.

Real-life examples

  • simple usage
  • using container
  • using typeorm (manual relation squeries)
  • class-validator autovalidation
  • interfaces and inheritance
  • authorization guards usage
  • using typeorm (lazy relations)

JavaScript support

The main goal of TypeGraphQL is to get rid of SDL schema and TS interfaces duplication in favor of one single source of truth (classes with decorators). However, after adding new features like dependency injection, validation, authorization and subscriptions, there are some benefits of using this library instead of pure graphql-js or graph-tools.

Technically, it would be possible to use TypeGraphQL with babel's transform-class-properties and transform-decorators-legacy plugins and some modification in decorators signature and logic.

It also would be nice to support TypeScript compilation with Babel 7 using @babel/preset-typescript and a bunch of decorators/metadata plugins.

However I'm not sure if there's a demand for this feature.
So if you are interested, please ๐Ÿ‘ so I will know that I should implement it ๐Ÿ˜‰

Base enum support

API Draft

export enum Direction {
  Up = "UP",
  Bottom = "BOTTOM",
  Down = Bottom,
  Left = "LEFT",
  Right = "RIGHT",
}
// or
export enum Direction {
  Up,
  Bottom,
  Down = Bottom,
  Left,
  Right,
}

// no decorators on enums means manually register enum (or maybe assume `object` === enum?)
registerEnum(Direction);

// usage in definitions
@ObjectType()
class Movement {
  @Field(type => Direction)
  direction: Direction;
}

// usage in resolvers
const mov = new Movement();
mov.direction = Direction.Right;

switch (mov.direction) {
  case Direction.Right:
    console.log("right!");
    break;
  case Direction.Left:
    console.log("left!");
    break;
  // etc.
}

Better checking and meaningfull errors

Please feel free to comment in this issue and tell what check is missing or what check throw not detailed errors!

  • more info about the need to provide explicit type
  • more info about problems with determining GraphQL type for property/argument (@esindger)
  • using @Args with @InputType or without @ArgsType
  • inform about missing reflect-metadata polyfill
  • missing @InterfaceType on class provided to { implements: SomeClass } (@gdanov)
  • more details in message when GeneratingSchemaError occured
  • duplicated arg name
  • description/depreciation on not supported field
  • multiple usage of @Args()
  • field resolver not matching resolver object type
  • using @Arg with @ArgsType class
  • duplicated query/mutation name (now it overwrites)
  • overwriting interface/base class field types
  • creating field resolver for method resolver
  • no resolver files match glob pattern
  • detect ES5 compilation (no Function.name)
  • detect undefined or other invalid values provided by mistake in type => X
  • detect wrong target setting and arrow function detection issue (#206, #219)
  • more specific error message when root Query is missing (#218)
  • using defaultValue option in @Field placed in @ObjectType
  • abstract type is used directly in GraphQL schema
  • checking implementation of all abstract interface field resolvers
  • inform that decorators don't work on static methods (@karladler)
  • duplicated types/enums before schema auto-check (with stacktrace to point source files)
  • ...others ๐Ÿ˜œ

Recursive types?

Author has posts and posts have authors (i.e a recursive type). Compiling will result in Post undefined since Post depends and Authors and Authors depend on Post. How should you handle this case?

@ObjectType({ description: 'An author...' })
export class Author {
	@Field(type => ID)
	id: string;
	@Field() firstName: string;
	@Field() lastName: string;
	@Field(type => [Post])
	posts: Post[];
}

@ObjectType({ description: 'A post...' })
export class Post {
	@Field(type => ID)
	id: string;
	@Field() title: string;
	@Field(type => Int)
	votes: number;
	@Field(type => Author)
	author: Author;
}

Automatic validation

Integration with class-validator with options and ability to disable feature.

Does mutation requires all inputs in a specific field (e.g "input")?

The mutation examples show that the inputs have to be put under a specific field e.g (@arg("input")). When I use @Args() instead, I'm getting this error when the server starts

(node:15051) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'target' of undefined
    at params.reduce (/web/node_modules/type-graphql/schema/schema-generator.js:240:69)

Is it a must to use @arg("input")?

This example won't work:

    @Mutation(returnType => ItemLike)
    async updateItemLikes(@Args() {id, userId}: UpdateItemLikesArgs) {
               return ....
    }

Importing resolvers from file path glob

Ability to specify glob paths for resolvers files instead of explicitly importing them and registering:

const schema = await buildSchema({
  resolvers: [
    "./src/resolvers/**/*.ts",
    "./src/**/*.resolver.ts",
  ],
});

Middleware and afterware support

Custom resolvers with @UseBefore and @UseAfter decorators, global middlewares, etc.
Support for catching errors only (for logging purpose or sth).

Repository isn't injected into resolver

I learnt of this library from a discussion in routing controller. I've been testing the typeorm sample.
When I made a query

{
   recipe(id: 2) {
       title
   }
}

I got this error "message": "Cannot read property 'findOneById' of undefined".
So obviously the repository isn't injected into the resolver. What is wrong with the sample below?

import {Args, ArgsType, Field, ID, Query, Resolver} from "type-graphql";
import {Recipe} from "../entity/Recipe";
import {Repository} from "typeorm";
import {OrmRepository} from "typeorm-typedi-extensions";

@ArgsType()
class FindRecipeArgs {
    @Field(type => ID)
    id: number;
}

@Resolver(objectType => Recipe)
export class RecipeResolver {
    public constructor(
        @OrmRepository(Recipe) private readonly recipeRepository: Repository<Recipe>,
    ){}
    @Query(returnType => Recipe, { nullable: true })
    async recipe(@Args() { id }: FindRecipeArgs): Promise<Recipe | undefined> {
        return this.recipeRepository.findOneById(id);
    }

    @Query(() => Recipe, { array: true })
    recipes(): Promise<Array<Recipe>> {
        return this.recipeRepository.find();
    }

}

Library version:

    "type-graphql": "^0.8.0",
    "typedi": "^0.7.1",
    "typeorm": "^0.1.16",
    "typeorm-routing-controllers-extensions": "^0.1.0",
    "typeorm-typedi-extensions": "^0.1.1",

More examples

  • integration with apollo-engine (apollo-cache-control)
  • usage with mongoose (typegoose)
  • usage on client side (Apollo client state)
  • using class mixins
  • GraphQL Modules
  • Join Monster
  • graphql-shield integration
  • using relations betweens types (user -> recipes -> comments)
  • testing examples (unit and e2e)
  • AWS lambda (apollo-server-lambda)
  • sample fullstack project with React and Apollo

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.