SpoonX/aurelia-api

Question: Configure endpoints from Swagger

Closed this issue · 14 comments

Has anyone explored the possibility of configuring aurelia-api endpoints from a swagger.json definition?

I like the way the swagger parameters object has types: header, path, query, body which could be used to expand upon and standardize the way aurelia-api builds paths and query strings.

Perhaps there would be implications to aurelia-orm as well since swagger definitions contain schema.

Thanks and keep up the great work!

sounds like a good idea

Perhaps this would be helpful:
https://github.com/swagger-api/swagger-js

@joshbooker I thought about doing something like that before I started working on aurelia-orm. I'm just not really sure how this would work.

Swagger-based apis do basically the same thing. It's useful for documentation, but I'm not sure how this would then do anything for aurelia-api. It needs the endpoint to fetch the json. So in that sense I suppose it could then be used to validate outgoing requests.

What do you have in mind?

IMHO this is something that pertains to aurelia-orm, not aurelia-api. This library should maintain its focus to a simple wrapper with low-level interface.
A schema, whatever its format, is meant to describe the entities and related operations available on a given API, and traditionally this is consumed by ORM libraries (see for example breezejs).

Perhaps aurelia-orm is a better place for this, but there may be aspects in swagger definition that pertain to aurelia-api as well. For example, given the endpoint to the swagger definition, the paths & operations available at the resource are discoverable. Also included are parameter definitions. Parameters may be needed in the header, path, querystring, or body. Swagger makes these aspects of an API discoverable including where they apply to the resource. aurelia-api could use the path parameters to build the path using path templating and use the query parameters to build the querystring (criteria object in your implementation). Point is, to use this in orm with api, some changes to api would be needed.

Point is, to use this in orm with api, some changes to api would be needed.

Actually, this isn't true.. I'm running a modified version of aurelia-orm that talks to an HATEOAS api, and builds request paths and query strings dynamically. Everything you need is exposed by aurelia-api: a method, a path, and a query string, against a registered endpoint...
According to the Single Responsibility Principle, the aurelia-api lib is doing what it is aimed to, and this shouldn't change.
You're talking about Swagger definitions, that I don't like and don't use in my API. I use HAL or JSON Schema, and I can use aurelia-api in my ORM implementation simply because it does not get into my way.
An ORM can be developed to consume different schema languages, and map these to instructions for the various components it drives: one or more endpoints, entities, repositories with auto-generated wrappers around aurelia-api methods, etc. The implementation can even decide to not dynamically generate all of this at runtime, but instead provide one or more CLI generators that given a schema produce the various classes.
Think about this: a filesystem driver should know the difference between a text file, an image, a video, or simply how to deal with reading/writing blocks of bytes? ;)

First thanks for the discussion and your time.

I see your point about single responsibility. I'm not suggesting the model schema be used in aurelia-api. Just that the api's paths, endpoints, methods and parameters could be discoverable.

For example, how would you handle this:
/api/Categories
only GET
/api/Categories({CategoryID})
singleton methods: GET, POST, PUT, PATCH, DELETE

Correct me if I'm wrong, but I believe aurelia-api assumes the path is
/api/Categories/1 instead of /api/Categories(1).

Since /api/Categories(1) and /api/Categories(2) are different paths and getRequestPath() doesn't handle path templates, wouldn't you have to register an new endpoint for every singleton request?

Perhaps the concept of Path Parameters using Path Templates like in the swagger spec would help with this(?)

Thanks again.

request('GET', `Categories(${id}`)
find(`Categories(${id})`)
findOne(`Categories(${id})`)

If you have access to all the parts that makes up a Request object, then nothing prevents you from writing a conversion layer from a given schema instance and a set of operations.
My point is simply that it shouldn't be added to aurelia-api.
One possibility could be to write another lib that deals with that abstraction, and in turns that lib could be leveraged by a smart ORM to automate the boring task of writing entities, repos etc by hand.

This issue was moved to SpoonX/aurelia-orm#237

@doktordirk BTW adding a pathTemplate parameter to the config, as @joshbooker suggested, could be a good addition with a small impact..
The default will be /${id}, but one can simply change it to (${id}) and be able to use the methods passing an id parameter instead of hard-coding it in the path like my examples above.
What do u think?

impact will be small but i fear that'll open the box of pandora 😄 anyways, let's make a new issue for that though

Curious, can criteria object be used synonymously with querystring parameters?
like:
.find('categories', {
$select: 'CategoryID,CategoryName',
$filter: 'CategoryID gt 5',
$orderby : 'CategoryName'
})
would request:
/api/Categories?$filter=CategoryID gt 5&$select=CategoryID,CategoryName&$orderby=CategoryName

@joshbooker Yes, criteria in the find signature should have better named criteriaOrId. If it is a POJO it is used to construct the query and appended to the resource parameter that is in turn appended to the baseUrl of the endpoint.

@Nexbit thanks. queryOrId might be a better name.