Giter VIP home page Giter VIP logo

Comments (5)

renatocassino avatar renatocassino commented on August 28, 2024

I have the same problem :/
I "solved" with a horrible solution using override in method didReceiveResponse. I returned a Promise instead of TResult (using typescript) and in this promise, I got the content and return request and result

didReceiveResponse<TResult = any>(response: any, request: Request): Promise<any> {   
    const parent = super.didReceiveResponse.bind(this);

    return new Promise(async (resolve) => {
      const body = await parent<TResult>(response, request);

      return resolve({
        body,
        req: request,
      })
    });
  }

But there are several problem in this solution :/

Isnt possíble to override a syncronous method with an asyncronous method (this explains why I returned a Promise, instead of use an async override)
The generics for methods get, post, put, patch and delete have no sense anymore, because, in these contracts, the return is the generics.

const { req, body } = await this.get<MyType>('/uri'); // Error
// I changed to

const { req, body } = await this.get('/uri');

return body as MyType;

Too many problems, but works for me
I'm waiting for a better solution

from datasource-rest.

renatocassino avatar renatocassino commented on August 28, 2024

I refactored this and made a better solution. I created an interface like Axios response and overloaded the methods get, put, delete, patch and post.

// Interface with response, like axios
interface ResponseInterface<T = any>  {
  data: T;
  status: number;
  headers: any;
  request?: any;
}

class BaseAPIDataSource extends RESTDataSource {
  didReceiveResponse(response: any, request: Request): Promise<any> {
    // I'm getting some metrics here to prometheus
    return this.formatResponse(response, request);
  }

  async formatResponse(response: any, request: Request): Promise<ResponseInterface> {
    if (response.status >= 500) {
      await super.didReceiveResponse(response, request);
    }
    const data = await this.parseBody(response);
    return {
      data,
      status: response.status,
      headers: response.headers,
      request,
    };
  }

  // Now I'm overloading the parent methods only changing the type response
  
  protected async get<TResult = any, R = ResponseInterface<TResult>>(
    path: string,
    params?: URLSearchParamsInit,
    init?: RequestInit,
  ): Promise<R> {
    return super.get(path, params, init);
  }

  protected async put<TResult = any, R = ResponseInterface<TResult>>(
    path: string,
    body?: Body,
    init?: RequestInit,
  ): Promise<R> {
    return super.put(path, body, init);
  }

  protected async post<TResult = any, R = ResponseInterface<TResult>>(
    path: string,
    body?: Body,
    init?: RequestInit,
  ): Promise<R> {
    return super.post(path, body, init);
  }

  protected async patch<TResult = any, R = ResponseInterface<TResult>>(
    path: string,
    body?: Body,
    init?: RequestInit,
  ): Promise<R> {
    return super.patch(path, body, init);
  }

  protected async delete<TResult = any, R = ResponseInterface<TResult>>(
    path: string,
    params?: URLSearchParamsInit,
    init?: RequestInit,
  ): Promise<R> {
    return super.delete(path, params, init);
  }
}

The usage now is like Axios and the type validation works

  const { data, headers, status } = await this.get<MyCustomType>('/my/path', { page: 1 });

  console.log(data, headers, status);

from datasource-rest.

glasser avatar glasser commented on August 28, 2024

Does overriding parseBody (which is protected) help here?

class MyAPI extends RESTDataSource {
  protected parseBody(response: Response): Promise<object | string> {
    return super.parseBody(response).then(result => {
      return augmentResultWithHeaders(result, response.headers);
    });
  }
}

Or is that tough because parseBody doesn't know which particular API it is implementing?

from datasource-rest.

devdudeio avatar devdudeio commented on August 28, 2024

I can highly recommend to switch to your own DataSource and use axios instead of using the RESTDataSource. Its giving you more flexibility in the long run.

from datasource-rest.

StarpTech avatar StarpTech commented on August 28, 2024

If you need a more flexible data source you could try https://github.com/StarpTech/apollo-datasource-http. It's also listed here https://www.apollographql.com/docs/apollo-server/data/data-sources/

from datasource-rest.

Related Issues (20)

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.