Creating Resolvers that work with an external FHIR Server - graphql

I am exploring this library
https://github.com/Asymmetrik/graphql-fhir
It does not contain logic for how to implement resolvers for a 3rd party FHIR Server.
Has anyone attempted this?

I'll add some pseudo code below, but that library is essentially a wrapper and has no backend, so you can definitely use it to wrap other FHIR servers. GraphQL resolvers can resolve sync or async. So if we took the patient resolver (https://github.com/Asymmetrik/graphql-fhir/blob/master/src/resources/4_0_0/profiles/patient/resolver.js), for example, and wanted to connect it to a third party server, like HAPI or some other server. You could implement it like so (pseudocode so untested):
module.exports.getPatient = function getPatient(root, args, context = {}, info) {
// args contains the arguments in GraphQL format, note that these may
// not map directly to another FHIR server for naming restriction reasons
// e.g. fooBar in graphql might be foo-bar in REST
// Make an HTTP request, use any http library, for example, fetch
return fetch('some/fhir/server/patient', {
method: 'post',
body: JSON.stringify(args) // remember args may need to be mapped
})
.then(response => response.json())
.then(results => {
// Make sure the response matches what the resolver expects, in this
// case, a single patient
return results;
});
};
There is an example at https://github.com/Asymmetrik/graphql-fhir/blob/master/FAQ.md#resolvers, but that is loading a local patient, you just need to make an HTTP request to some 3rd party server and return the results asynchronously. For handling errors, make sure to check out this as well, https://github.com/Asymmetrik/graphql-fhir/blob/master/FAQ.md#resolvers.

Related

How to retrieve only the number of seats for all the subscriptions of my customers? (Google Workplace Reseller)

I am using the following JS code to retrieve seats details for all the subscriptions of my customers.
gapi.client.reseller.subscriptions.list()
.then(function(response) {
// Handle the results here (response.result has the parsed body).
console.log("Response", response);
},
function(err) { console.error("Execute error", err); });
However, it's returning all of their other information as well. How can I customize it so that it only returns the number of seats?
Google APIs has a standard parameter called fields that allows you select which fields are included in the response (see documentation on Docs API).
In Google API Client Library for JavaScript (aka gapi) you can simply add the parameters in an object when making a request. In your case this should work:
gapi.client.reseller.subscriptions.list({
fields: [
'nextPageToken',
'subscriptions/subscriptionId',
'subscriptions/seats/numberOfSeats',
].join(',')
})
It's important to keep all fields that you need including control fields like nextPageToken. You can read more about the format used here.

Apollo GraphQL mutation signature equivalent to PUT

I'm trying to effectively do a PUT request with GraphQL
Mutation:
export const UPDATE_CAT = gql`
mutation updateCat($catRef: RefInput, $payload: CatInput) {
updateCat(ref: $catRef, input: $payload) {
${ref}
}
}
`;
Query variables:
{
"catRef": {
"id": "7b342789-e527-42a6-997b-cfe2fb6bdb07",
"typename": "cat.beacon.Beacon"
},
"payload":{
"position": null,
}
}
Although this seems to wipe all of the props on the cat entity (it does not delete the resource). Is this the correct syntax for a PUT like request?
First of all, I think it's worth to note that graphql is protocol agnostic. That means any transport protocol can be used, not necessarily HTTP (despite HTTP is used in most cases).
Also, what do you mean by PUT like request? As I understand, you state that HTTP PUT method is used to patch data. Which might not be true. It depends on how you implement this. You can easily create a REST API that is accepting data via GET and sending via POST or PUT method despite this is not recommended by best practices.
The same situation here with your problem. It's not about your mutation signature, it's about mutation resolver implementation.
In order to make this work, you should determine in your resolver function on a server if this is a new or existing resource and handle both scenarios properly.
How can you check if this is a new resource? Id prop will be undefined in this case, right?
If you are working with third-party api then check it's docs.

Admin on rest - RestClient & Create operation return params + id instead of response.data

In the two REST client (simple & json) provided in the module, on the CREATE operation we have this :
case CREATE:
return { data: { ...params.data, id: json.id } };
params is the data sended by the client to the server, json is the data that the server returned.
Why is better to return client data than server response ?
In the two REST clients, we assume that we can't prejudge what the server will return to us, but the new element's id.
And we're assuming that the data provided for creation will allow the correct display of the list.
But of course, if this is not your case (i.e. you know exactly what the server will return, including some information not requested at creation), you can decorate an existing client or create your own.

mocha: can't use one request for mutlple `it` test

const request = require('supertest');
const server = request('http://localhost:9001');
describe('Get /static/component-list.json', function() {
const api = server.get('/static/component-list.json');
it('should response a json', function(done) {
api.expect('Content-Type', /json/, done);
});
it('200', function(done) {
api.expect(200, done); // This will failed
// server.get('/static/component-list.json').expect(200, done); // This will successed
});
});
when reuse api in the second test case, mocha will raise a Error:
The result of mocha test/api command:
How can I request the url once and use in multiple it case.
Solution
You have to create a new request for each test (each it) that you want to run. You cannot reuse the same request for multiple tests. So
describe('Get /static/component-list.json', function() {
let api;
beforeEach(() => {
api = server.get('/static/component-list.json');
});
Or if you want to reduce the number of requests made, then combine all your checks on the request into a single Mocha test.
Explanation
If you look at the code of supertest, you'll see that when you call an expect method with a callback, expect calls automatically calls end. So this:
api.expect('Content-Type', /json/, done);
is equivalent to this:
api.expect('Content-Type', /json/).end(done);
The end method is provided by superagent, which is what supertest uses to perform requests. The end method is what kicks off the request. It means you are done setting up the request and want to fire it off now.
The end method calls the request method, which is tasked with using Node's networking machinery to produce a Node request object that is used to perform the network operation. The problem is that request caches the Node request is produces but this Node request object is not reusable. So ultimately, a superagent or supertest request cannot be ended twice. You have to reissue the request for each test.
(You could manually flush the cached object between tests by doing api.req = undefined. But I strongly advise against this. For one thing, whatever optimization you might think you'd get is minimal because the network request still has to be made anew. Secondly, this amounts to messing with superagent's internals. It may break with a future release. Third, there may be other variables that hold state that might need to be reset together with req.)

Ember Data update POST when it should be PUT

I'm working on an Ember.js app. I have an update function, part of an ObjectController.
The function should save my updated model, however when I call save(); it sends a POST request not a PUT request. (Tested in Chrome.)
Why would that happen? How can I make sure a PUT request is sent for updates?
Here is my code:
customer = this.get('model');
customer.set('name', 'New name');
customer.save();
For extra reference, when I log the "dirtyType" with console.log( customer.get('dirtyType') ); it says "updated".
Any help very much appreciated!
UPDATE
I've adjusted the sample code above to make it clearer, I am NOT creating a new model and wanting to use PUT. I have an existing model that I need to update.
I'm not sure if your workaround is correct in the land of PUT vs POST.
TL;DR PUT should define the resource (by Request-URI), but we don't do that during creation, so we shouldn't be using a POST. Override the create/save if you need this for your server, instead of hacking the isNew property, which may come back to bite you.
Put
9.6 PUT
The PUT method requests that the enclosed entity be stored under the
supplied Request-URI. If the Request-URI refers to an already
existing resource, the enclosed entity SHOULD be considered as a
modified version of the one residing on the origin server. If the
Request-URI does not point to an existing resource, and that URI is
capable of being defined as a new resource by the requesting user
agent, the origin server can create the resource with that URI. If a
new resource is created, the origin server MUST inform the user agent
via the 201 (Created) response. If an existing resource is modified,
either the 200 (OK) or 204 (No Content) response codes SHOULD be sent
to indicate successful completion of the request. If the resource
could not be created or modified with the Request-URI, an appropriate
error response SHOULD be given that reflects the nature of the
problem. The recipient of the entity MUST NOT ignore any Content-*
(e.g. Content-Range) headers that it does not understand or implement
and MUST return a 501 (Not Implemented) response in such cases.
If the request passes through a cache and the Request-URI identifies
one or more currently cached entities, those entries SHOULD be
treated as stale. Responses to this method are not cacheable.
The fundamental difference between the POST and PUT requests is
reflected in the different meaning of the Request-URI. The URI in a
POST request identifies the resource that will handle the enclosed
entity. That resource might be a data-accepting process, a gateway to
some other protocol, or a separate entity that accepts annotations.
In contrast, the URI in a PUT request identifies the entity enclosed
with the request -- the user agent knows what URI is intended and the
server MUST NOT attempt to apply the request to some other resource.
If the server desires that the request be applied to a different URI,
Custom Adapter
App.ApplicationAdapter = DS.RESTAdapter.extend({
createRecord: function(store, type, record) {
var data = {};
var serializer = store.serializerFor(type.typeKey);
serializer.serializeIntoHash(data, type, record, { includeId: true });
//return this.ajax(this.buildURL(type.typeKey), "POST", { data: data });
return this.ajax(this.buildURL(type.typeKey), "PUT", { data: data });
},
updateRecord: function(store, type, record) {
var data = {};
var serializer = store.serializerFor(type.typeKey);
serializer.serializeIntoHash(data, type, record);
var id = get(record, 'id');
// you could do the same here, but it's even more incorrect
return this.ajax(this.buildURL(type.typeKey, id), "PUT", { data: data });
},
});
http://www.ietf.org/rfc/rfc2616.txt
Thank you for all of your help guys, however I have found the issue and it is ridiculously silly.
The API I have been using had a new flag "is_new" and that had been added to the model and was overwriting the "isNew" property.
Causing Ember (and me) to get very confused.
I've tweaked the API and all is good in the world!
If the model was created with createRecord, and thus has isNew == true and you call save() the expected behavior is POST. Once the record has been persisted, and it is changed, and thus isDirty == true but isNew == false then the save() will be a PUT.
This is described in the Models Guide.

Resources