0
votes

I am writing a resolver to fetch data from REST api to graphql backend function using typescript and type-graphql.The issue I am facing is I am getting data from API with all props but I want to return only selected fields in front end. How to return only selected fields?

Here is my scenario. I have react app as front end. I will write all graphql queries in fronetend app. There is apollo client in front end which connects to graphql in backend. Backend is node app written in typescript. My backend fetches data from rest api and serves to front end via apollo server. We use type-graphql in backend

Here in this question I have doubts for backend.

I have following type (defined in backend as personInfo.ts)

import { ObjectType, Field } from "type-graphql";

@ObjectType("PersonInfo")
export class PersonInfo {
  @Field({ nullable: true }) firstName: string;
  @Field({ nullable: true }) lastName: string;
  @Field({ nullable: true }) registrationNo: string;
  @Field({ nullable: true }) personCode: string;
  @Field({ nullable: true }) personCapabilities: string;
}

I am using above type in my resolver like below: (defined in backend as personInfoResolver.ts) This graphql resolver will fetch data from rest api using function written in next part. This function has issue as stated in code below.

import { Query, Resolver, Arg } from "type-graphql";
import { PersonInfo } from "../types";
import { GetPersonInfo } from "./api/helpers";

@Resolver((of) => PersonInfo)
export class PersonInfoResolver {
  @Query((returns) => PersonInfo, { nullable: true })
  async PersonInfo(@Arg("serialNo") serialNo: string) {
    console.log(await GetPersonInfo(serialNo)); //<--this logs full object received from api with all the fields
    return await GetPersonInfo(serialNo); //when queried from graphql playground, i get null for selected values even if previous line prints all data
  }
}

Here is function to get data in api helper (Defined in backend to connect to api and get data.) WOrks fine and gets all objects from rest api.

export const GetPersonInfo = async (serialNo: string) => {
  var personInfoURL = "url" + serialNo;
  if (!serialNo) {
    return "";
  }
  const response = await posApi
    .get(personInfoURL)
    .then(function (response) {
      return response.data;
    })
    .catch(function (error) {});

  const data = await response;

  return data;
};

I am testing above code using graphql playground using following query.

  {
    PersonInfo(serialNo:"201123030"){
     firstName
     lastName
     registrationNo
     registrationNo
     personCapabilities

 }
}
1
This question is incomplete, where's your graphql-query/mutation?Joel
Or, is that what you are wondering? How to write graphql-schema-functions?Joel
@Joel query will be in front end react app. Right now I am writing backend in node and testing using graphql play ground.Added query in questionGaurav Chauhan
I'll upvote it for you, its a good question although pretty messy. Please check my answer below, it shows you what you want.Joel
Have you had a chance to look at my solution?Joel

1 Answers

1
votes

Your question is unclear to me, but I'll try to help you out.

First of all, that GraphQL schema you provided is invalid.

In the Playground, you should write:

{
    PersonInfo(serialNo: "201123030") { //not DetailsInfo
        firstName
        ...
    }

}

Given that your entity looks like this:

@Column()
@Field({ nullable: true }) firstName: string;
@Column()
@Field({ nullable: true }) lastName: string;
@Column()
@Field({ nullable: true }) registrationNo: string;
@Column()
@Field({ nullable: true }) personCode: string;
@Column()
@Field({ nullable: true }) personCapabilities: string;

And that your resolver looks like this:

@Resolver(PersonInfo)
export class PersonInfoResolver {
  @Query(() => PersonInfo, { nullable: true })
  async PersonInfo(@Arg("serialNo") serialNo: string): Promise<PersonInfo> {
    return await GetPersonInfo(serialNo); //when queried from graphql playground, i get null for selected values even if previous line prints all data
  }
}

I recommend running

npm i -D @graphql-codegen @graphql-codegen/cli @graphql-codegen/typescript @graphql-codegen/operations @graphql-codegen/typescript-react-apollo

which allows for automatic schema-generations and typesafety in your project.

Create a file called codegen.yml in your root-directory of your react-project (same location as package.json)

overwrite: true
schema: "http://localhost:4000/graphql"
documents: "src/graphql/**/*.graphql"
generates:
  src/generated/graphql.tsx:
    plugins:
      - "typescript"
      - "typescript-operations"

Create the folder generated in src/*.

OR, change the structure above to whereever you want the schemas to be generated.

You first need to create personinfo.query.graphql in src/graphql/queries/*

(You could also create another folder called src/graphql/mutations/ here)

personinfo.query.graphql

query PersonInfo($serialNo: String!) { 
     personInfo(serialNo: $serialNo) {
         firstName,
         lastName,
         registrationNo,
         personCode,
         personCapabilities  //or whatever subset of fields you want.
     }
}

In your console type: graphql-codegen --config codegen.yml and the files will be generated. Open graphql.tsx now and see what it has created. Pretty neat right?

Then in your react-component just do:

export const MyComponent: React.FC<{}> = ({}) => {

    const [{data}] = usePersonInfoQuery({/*your serialNo here*/}); //this function will have been generated now
    //then you have access to the fields you supplied to `personinfo.query.graphql`
    const fName = data.personInfo.firstName;
    const lName = data.personInfo.lastName;

}