how graphql tools addSchemaLevelResolver function works - graphql

As I understood addSchemaLevelResolver function add a root level resolver on schema and cut off the all other resolvers. And I tried that method like in the below.
if (process.env.DEV === true) {
schema = addSchemaLevelResolver(schema, () => {
throw new Error("Internal Server Error!");
});
}
Yes this function resolving and throw error when first call on some query or mutation on the schema. But after that it's not throwing the error as I expected and not blocking resolvers in the schema. Is this function only work for first call or is that a bug or am I doing it wrong?

addSchemaLevelResolver has been removed in favor of Resolvers Composition.
I believe addSchemaLevelResolver and the new Resolvers Composition would literally traverse the schema and add resolve function to each Type and Field.

Related

How can I stop an Apollo GraphQL query with required exported variables from fetching when those variables are removed

The Problem
When navigating away from query components that use the state of the app route as required variables, I get GraphQL errors of the sort:
Variable "$analysisId" of required type "ID!" was not provided.
"Navigating away" means, for example, going
from: /analysis/analysis-1/analyse/
to: /user-profile/
Background
I am building an SPA using Apollo GraphQL, and I have some queries which follow this pattern:
query Analyse($analysisId: ID!) {
location #client {
params {
analysisId #export(as: "analysisId")
}
}
analysis(analysisId: $analysisId) {
id
# ... etc
}
}
The location field gets a representation of the SPA router's state. That state is held in an Apollo client "reactive variable". Query components are programmed to not begin subscribing to the query unless that reactive variable exists and has the required content.
shouldSubscribe(): boolean {
return !!(locationVar()?.params?.analysisId);
}
Params represents express-style URL params, so the route path is /analysis/:analysisId/analyse.
If the user navigates to /analysis/analysis-1/analyse, the query component's variables become: { analysisId: "analysis-1" }`. This works fine when loading the component.
What I Think is Happening
When the component connects to the DOM, it checks to see if it's required variables are present in the router state, and if they are, it creates an ObservableQuery and subscribes.
Later, when the user navigates away, the ObservableQuery is still subscribed to updates when suddenly the required analysisId variable, exported by the client field location.params.analysisId is nullified.
I think that since the ObservableQuery is still subscribed, it sends off the query with null analysisId variable, even though it's required.
What I've Tried
By breaking on every method in my query component base class, I'm reasonably sure that the component base class is not at fault - there's no evidence that it is refetching the component when the route changes. Instead, I think this is happening inside the apollo client.
I could perhaps change the schema for the query from analysis(analysisId: ID!): Analysis to analysis(analysisId: ID): Analysis, but that seems roundabout, as I might not have control over the server.
How do I prevent apollo client from trying to fetch a query when it has required variables and they are not present?
This seems to be working fine so far, in my HttpLink, src/apollo/link/http.ts:
import { ApolloLink, from } from '#apollo/client/link/core';
import { HttpLink } from '#apollo/client/link/http';
import { hasAllVariables } from '#apollo-elements/lib/has-all-variables';
const uri =
'GRAPHQL_HOST/graphql';
export const httpLink = from([
new ApolloLink((operation, forward) => {
if (!hasAllVariables(operation))
return;
else
return forward(operation);
}),
new HttpLink({ uri }),
]);

Creating Resolvers that work with an external FHIR Server

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.

How to delete all objects of Class in Parse Server?

I want to delete all object of my class with jobs. I have created my job and I wrote below code to achieve my goal but my code did not work.
Parse.Cloud.job("deleteWeeklyScore", (request) => {
const mySchema = new Parse.Schema('WeeklyGameScore');
mySchema.purge();
});
I can delete field from my schema but delete all objects does not work
purge() returns a promise. You have to resolve your promise.
schema.purge().then(...) or await schema.purge() or return schema.purge()
I don't know if Job resolves a promise.

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.

why i am getting No query results for model in laravel?

When i search by city name which is available in my database table it will show the result but when i search by unknown city which is not available in my database table it says -No query results for model [App\City]. i am sharing you the code and screenshot see error screenshot
actually i want to redirect to 401 page if the city is not found in my database table
Here is my route
Route::get('teacher-jobs-by-city/{city}','TeacherJobsController#by_location');
Here is my function
public function by_location($location_id='')
{
$data= array();
$location = City::where('slug',$location_id)->where('status','1')->firstOrFail();
$items= Subject::orderBy('id','asc')->get();
$data['location']=$location;
//$subjects = [''=>'Select Subject'] + Subject::lists('subject_title','id')->toArray();
//$city = [''=>'Select City'] + City::lists('name','id')->toArray();
$active_class ='Select Subject to see job Openings';
return view('frontend.teacherjobs.by_location',compact('active_class','data','items'));
}
That's because you are using the firstOrFail() method, that as named, fails if theres no result by throwing an Exception that will be redered as "No query results for model ..." message.
If you want to it don't fail, you can:
Surround your query with a try-catch block, handling the exception and return some message
Replace the firstOrFail() method by first()
You can handle that kind of error by modifying the way Illuminate\Database\Eloquent\ModelNotFoundException Exception are handle. In the App\Exceptions\Handler class change the render method to look like this
public function render($request, Exception $exception)
{
if($exception instanceof ModelNotFoundException){
return redirect("/error_page", 401)->with('error', $e->getMessage());
}
return parent::render($request, $exception);
}
Within the redirect your must put the route to which you want to be redirected, I put /error_page just for sample purpose.
You can learn more on Error Handling'
Don't forget to import the ModelNotFoundException like this use Illuminate\Database\Eloquent\ModelNotFoundException;
Adding on to the answer by Elias Soares, This happens because laravel generates an "Illuminate\Database\Eloquent\ModelNotFoundException" exception if firstOrFail don't return results.
Reference: https://laravel.com/docs/5.8/eloquent#retrieving-single-models
It's upto you how you want to handle this exception. If using firstOrFail -> to first() solution
After replacing firstOrFail with first, You would get the error: "Trying to get property of non object", That's because your query didn't fetched anything, so it won't have attribute. For that you can place a check on the results of your query.
$location = City::where('slug',$location_id)->where('status','1')->first();
!empty($location->attribute)?$location->attribute:null;
Replace this:
$location = City::where('slug',$location_id)->where('status','1')->firstOrFail();
With this:
$location = City::where('slug',$location_id)->where('status','1')->first();

Resources