Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Custom Remote Methods returning Array of Object #311

Closed
2 of 7 tasks
spid3r opened this issue Jan 10, 2017 · 2 comments · Fixed by #336
Closed
2 of 7 tasks

Custom Remote Methods returning Array of Object #311

spid3r opened this issue Jan 10, 2017 · 2 comments · Fixed by #336

Comments

@spid3r
Copy link

spid3r commented Jan 10, 2017

What type of issue are you creating?

  • Bug
  • Enhancement
  • Question

What version of this module are you using?

  • 2.0.10 (Stable)
  • 2.1.0-rc.n (2.1 Release Candidate n)
  • Other
  • 2.1.0-rc.8.2

Write other if any:

Please add a description for your issue:

When creating a custom remote method which returns an array of objects (as another model definition type) the SDK will generate the wrong Observable return type.
So I want to return an array of objects which are actually defined as a model type.

Another problem is that the req argument should not be included as importing parameter if it is defined with http:{ source:'req'}. This req arguments are not exposed as import parameter but can be used for the javascript programming on the backend.

  Event.remoteMethod(
    'findByLocation', {
      http: {
        path: '/findByLocation',
        verb: 'get'
      },
      description: ["Returns an array of Events"],
      accepts:  [ {arg: 'location', type: 'GeoPoint', http: { source: 'query' }, description:'{"lat": 49.493179,"lng": 8.463423}', required:true },
                  {arg: 'radius', type: 'number', http: { source: 'query' }, required:true, default: 10},
                  {arg: 'unit', type: 'string', http: { source: 'query' }, description:'kilometers;meters;miles;feet;radians;degrees', required:true, default:"kilometers"},
                  {arg: 'req', type: 'object', http: { source: 'req' } }],
      returns: {
        arg: 'data',
        type:['event'],
        root: true
      }
    }
  );

Note the returns.type definition and the accepts arg:'req' definition.
This definition works in swagger perfectly and relates to the loopback documentation:
http://loopback.io/doc/en/lb3/LoopBack-types.html#array-types
So in the API Explorere everything looks nice:
explorer
The SDK seems to ignores the array definition. It generates an observable type of the plain object not an array of this object.
Additionally the SDK puts the req parameter as an argument which should not be done since it is not exposed via the API.
This is the SDK result:

  public findByLocation(location: any, radius: any, unit: any, req: any = {}): Observable<Event> {
    let _method: string = "GET";
    let _url: string = LoopBackConfig.getPath() + "/" + LoopBackConfig.getApiVersion() +
    "/events/findByLocation";
    let _routeParams: any = {};
    let _postBody: any = {};
    let _urlParams: any = {};
    if (location) _urlParams.location = location;
    if (radius) _urlParams.radius = radius;
    if (unit) _urlParams.unit = unit;
    if (req) _urlParams.req = req;
    let result = this.request(_method, _url, _routeParams, _urlParams, _postBody);
    return result.map((instance: Event) => new Event(instance));
  }

The result should be:

  public findByLocation<Event>(location: any, radius: any, unit: any, filter: LoopBackFilter = {}): Observable<Event[]> {
    let _method: string = "GET";
    let _url: string = LoopBackConfig.getPath() + "/" + LoopBackConfig.getApiVersion() +
    "/events/findByLocation";
    let _routeParams: any = {};
    let _postBody: any = {};
    let _urlParams: any = {};
    if (location) _urlParams.location = location;
    if (radius) _urlParams.radius = radius;
    if (unit) _urlParams.unit = unit;
    if (filter) _urlParams.filter = filter;
    let result = this.request(_method, _url, _routeParams, _urlParams, _postBody);
    return result.map((datum: Event[]) => datum.map((data: Event) => this.model.factory(data)));
  }

So if you would exclude the req param how can I then be able to apply a filter on my custom remote method?
In a version 2.1.0-beta.10 i did not have the {arg: 'req', type: 'object', http: { source: 'req' } } parameter defined but a filter like this: {arg: 'filter', type: 'object', http: { source: 'query' } }
This does now not work anymore since the SDK did change the filter on the request
https://github.com/mean-expert-official/loopback-sdk-builder/milestone/16
It was removed from the query and added to the http header because of this coding:

    if (urlParams.filter) {
      headers.append('filter', JSON.stringify(urlParams.filter));
      delete urlParams.filter;
    }

in base.service.ts
This is why I now have to access the request object directly in my remote method.

Thanks a lot for your help and this great framework!!!!

Cheers
Thorsten

@jonathan-casarrubias
Copy link
Collaborator

Hi @spid3r thanks for reporting.

I have verified and in fact there is no implementation to check if type is an array, so I will add it in the next version, also I will check the req property that should not go there, we have some validations for the type of http param, so maybe the req and res are missing, though I need to verify.

Cheers
Jon

@spid3r
Copy link
Author

spid3r commented Jan 11, 2017

Thanks @jonathan-casarrubias for your fast response!
So if you exclude the req and res param types (which would be correct) how would I then be able to pass a filter object (LoopbackFilter) to the remote method since it is now passed as HTTP Header to the request?

Cheers
Thorsten

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants