Passing feathers app object to TypeGraphQL using dependency injection

Viewed 214

I can't figure out how to pass my app object to my TypeGrapQL resolvers.

I created my types and resolvers and setup a graphql server using express-graphql. I was able to run the graph, but no luck in passing the app object to use the registered services.

My graphql.service.ts looks like this:

import { ServiceAddons } from '@feathersjs/feathers'
import { graphqlHTTP } from 'express-graphql'
import 'reflect-metadata'
import { buildSchemaSync } from 'type-graphql'
import { Container } from 'typedi'

import { Application } from '../../declarations'
import { Graphql } from './graphql.class'
import { ArticleResolver } from './resolvers/article.resolver'

// Add this service to the service type index
declare module '../../declarations' {
    interface ServiceTypes {
        graphql: Graphql & ServiceAddons<any>
    }
}

export default async function (app: Application): Promise<void> {
    const schema = buildSchemaSync({
        resolvers: [__dirname + '/resolvers/*.resolver.ts'],
        container: Container,
    })
    app.use(
        '/graphql',
        graphqlHTTP({
            schema: schema,
            graphiql: true,
        })
    )
}

and here's one of my resolver classes article.resolver.ts

import { Arg, Query, Resolver } from 'type-graphql'
import { Service } from 'typedi'

import { Application } from '../../../declarations'
import { Category } from '../types/category.type'

@Service()
@Resolver(Category)
export class CategoryResolver {
    constructor(private readonly app: Application) {}

    @Query((returns) => [Category])
    async categories() {
        try {
            const result = await this.app.service('category').find()
            return (result as any).data // TODO: Refactor to return result with pagination details
        } catch (err) {
            console.log('Categories resolver error', err)
            return []
        }
    }
}

I can't do this.app.service() as this.app is undefined

Im a little confused on how dependency injection works in TypeGrapQL, any help is appreciated.

Thanks

1 Answers

I managed to make it work, here's my solution if anyone has the same problem:

I created a Graphql class decorated with @Service from typedi that takes in an app object as such

import { Service } from 'typedi'
import { Application } from '../../declarations'

@Service()
export class Graphql {
    app: Application
    //eslint-disable-next-line @typescript-eslint/no-unused-vars
    constructor(app: Application) {
        this.app = app
    }
}

In my graphql.service.ts I initiated the class and passed down the instance to the typedi container

import { buildSchemaSync } from 'type-graphql'
import { Container } from 'typedi'

import { Application } from '../../declarations'
import { Graphql } from './graphql.class'

export default async function (app: Application): Promise<void> {
    const graphql = new Graphql(app)

    Container.set('graphql', graphql)

    const schema = buildSchemaSync({
        resolvers: [__dirname + '/resolvers/category.resolver.ts'],
        container: Container, // Pass the container to the resolvers
    })

    // Initialize our express graphql server
}

And Finally in my resolvers I am decorating the resolver with @Service and injecting the graphql instance to the constructor:


import { Application } from '../../../declarations'
import { Graphql } from '../graphql.class'

import { Inject, Service } from 'typedi'

@Service()
@Resolver(Category)
export class CategoryResolver {
    app: Application
    constructor(@Inject('graphql') private readonly graphql: Graphql) {
        this.app = this.graphql.app
    }

    // Queries and Mutations
}

This solved it to me, hope it comes with any help to you

Related