volbrene
volbrene

Reputation: 121

How can I use type-graphql and RESTDataSource

I wonder how it is possible to use RESTDataSource in type-graphql and thus cache correctly in a redis. I would be grateful for a small example.

At the moment I use the DI container to get a service, which is extended from the RestDataSource class, but this is not the right way.

BookmarkResolver.ts

import { Resolver, FieldResolver, Root, Query, Ctx, Authorized } from 'type-graphql';
import { DealService } from '../service/DealService';
import { AvailableLocale } from '../enum/AvailableLocale';
import { Bookmark } from '../entity/Bookmark';

@Resolver(_of => Bookmark)
export class BookmarkResolver {
  constructor(private dealService: DealService) {}

  @FieldResolver()
  async wordpressDeal(@Root() bookmark: Bookmark) {
    return await this.dealService.getDealById(bookmark.item_id, AvailableLocale.STAGING);
  }
}

DealService.ts

import { Service } from 'typedi';
import { AbstractService } from './AbstractService';
import { AvailableLocale } from '../enum/AvailableLocale';

@Service()
export class DealService extends AbstractService {
  baseURL = process.env.DEAL_SERVICE_URL;

  async getDealById(dealId: string | number, locale: AvailableLocale) {
    const response = await this.get(
      'deals/' + dealId,
      { locale }
    );

    return this.dealReducer(response);
  }

  dealReducer(deal: any) {
    return {
      id: deal.id || 0,
      title: deal.title
    };
  }
}

AbstractService.ts

import { RESTDataSource, HTTPCache } from 'apollo-datasource-rest';
import { Service } from 'typedi';

@Service()
export class AbstractService extends RESTDataSource {
  constructor() {
    super();
    this.httpCache = new HTTPCache();
  }
}

Upvotes: 12

Views: 1322

Answers (1)

Lauri Harpf
Lauri Harpf

Reputation: 1488

Share the RESTDataSource via ApolloServer's context. Use it in the resolver by accessing the context with the @Ctx() decorator.

1. Define a RESTDataSource

Define the data source according to the apollo-datasource-rest example.

export class TodoDataSource extends RESTDataSource {
  constructor() {
    super();
    this.baseURL = "https://jsonplaceholder.typicode.com/todos";
  }

  async getTodos(): Promise<Todo[]> {
    return this.get("/");
  }
}

2. Create an instance of the DataSource and put it in the Context

When you start the server, add data sources to the context by defining a function that creates the data sources.

const server = new ApolloServer({
  schema,
  playground: true,
  dataSources: () => ({
    todoDataSource: new TodoDataSource(),
  }),
});

3. Access the DataSource in the resolver

Use the @Ctx() decorator to access the context in the resolver so you can use the data source.

@Resolver(Todo)
export class TodoResolver {
  @Query(() => [Todo])
  async todos(@Ctx() context: Context) {
    return context.dataSources.todoDataSource.getTodos();
  }
}

Full, runnable example at https://github.com/lauriharpf/type-graphql-restdatasource

Upvotes: 4

Related Questions