Strongly typed GraphQL queries - javascript

I'm setting up a project with Vue CLI, using axios as my request library. All of the examples that I've seen uses a string as the query, e.g.
{
hero {
name
friends {
name
}
}
}
Since I'm using typescript and have typings for the entities, is there any way to generate the query using some kind of fluent framework or similar, so that I can work with intellisense instead of plain strings?

Most clients require you to provide the query as a string. You can use an IDE like GraphiQL, GraphQL Playground or Altair to provide features like autocompletion and syntax highlighting when writing your query. Certain editors also have plugins that offer similar functionality. If you're using TypeScript, you can typically use something like GraphQL Code Generator or Apollo CLI to then generate the types based on your queries and your schema.
The only client I'm aware of that is generated from your schema, allowing you to use a fluent API instead, is GraphQL Zeus.

Related

What is gatsbyContentfulFluid?

I'm learning Gatsby and GraphQL as a newbie and following this article
https://ibaslogic.com/gatsby-with-contentful-cms/
It has this code:
export const query = graphql`
query($slug: String!) {
contentfulBlogPost(slug: { eq: $slug }) {
title
publishedDate(formatString: "Do MMMM, YYYY")
featuredImage {
fluid(maxWidth: 750) {
...GatsbyContentfulFluid
}
}
}
}
`
I'm getting everything but not getting ...GatsbyContentfulFluid on my GraphQL query server.
C
an someone please explain what ...GatsbyContentfulFluid is?
Why we are using it with a spread operator?
and did I miss something while creating Contentful data that's why I'm not getting ...GatsbyContentfulFluid in my GQL query playground?
It's not a spread operator like we know it in JavaScript, in GraphQL stands for a query fragment.
A fragment's a way of querying a set of fields using reusable units. From GraphQL docs:
Let's say we had a relatively complicated page in our app, which lets
us look at two heroes side by side, along with their friends. You can
imagine that such a query could quickly get complicated, because we
would need to repeat the fields at least once - one for each side of
the comparison.
That's why GraphQL includes reusable units called fragments. Fragments
let you construct sets of fields, and then include them in queries
where you need to. Here's an example of how you could solve the above
situation using fragments:
In your case, the fragment is provided by gatsby-source-contentful and basically, is querying a fluid asset from Contentful, as you do normally when using gatsby-image for local files.
In other words, with ...GatsbyContentfulFluid fragment you are fetching the mandatory fields from Contentful assets that allow you to use a gatsby-image within the asset.
Fragments are not available in the GraphQL playground due to a limitation of the GraphiQL:
Note, due to a limitation of GraphiQL, you can not currently use these
fragments in the GraphiQL IDE.
So, you can use fragments (indeed, you should) but you will need to check your fetched data in your code (via console.logs or via debug breakpoints) directly since they are not available in the GraphQL playground.

Typescript and REST API response

Let me preface this question by saying that I am fairly new to typescript, but a long time JavaScript developer.
I have an existing JavaScript application that I am looking to transition over to typescript. In the JavaScript app, it makes a rest API call to fetch data, then checks to see if it exists, and then conditionally renders the app. In JavaScript, I can dynamically check to see if Properties exist on the response object and conditionally render that. In typescript, it throws an error because the data is of any type, and it doesn’t know if that property exists or not.
In a typescript application, is it pretty common to go create types for all of your API responses, so that you can get type safety on them? Using node as your backend, I could see a huge opportunity where you might be able to share backend and front end models. I am currently using .net core for my backend, and I am concerned I might be shooting myself in the foot trying to always create typescript models from the entity framework models.
Does anyone else use .net core for the backend and react on the front end? How do you handle API responses in typescript?
I can't tell you if it's common, but we write json-schema files for every endpoint. These schema files are:
Used to validate request bodies and generate errors.
Used to generate documentation.
Converted in to typescript types, which are used in both front- and backend.
We are using the same stack as you--.Net Core backend/React frontend--with typescript. The way we handle it is by creating types for the objects the backend sends us and then converting the dynamic checkers, like the ones you mention, into user-defined type guards.
So, roughly speaking, for the various data transfer objects the server returns we have a type/type guard pair that looks like this:
// type
export type SomeDto = { someKey: string; someOtherKey: number }
// type guard
export const isSomeDto = (returnedObj: any): returnedObj is SomeDto =>
returnedObject.someKey && typeof returnedObj === "string"
returnedObject.someOtherKey && tyepeof returnedObj === "number"
Then we have basically have the following in the fetching code:
const someReturn = fetchDatafromApi(endpoint)
if isSomeDto(someReturn) {
//now typescript will recognize someReturn as SomeDto
} else {
// throw or otherwise handle the fact you have bad data from the
// server
}
This way you get the dynamic checking in javascript at runtime and type safety at compile time. These guards aren't super-fun to write (and you'll want to unit test them all), and I imagine if the possible number of objects was bigger we'd opt for a more automated solution like #Evert mentions in the other answer. But for a few objects, and existing javascript validators, it is a pretty convenient way to get typing on your API returns.

Best practices for extendable and modifiable node (npm) modules

I need advice from the more experienced javascript(typescript) / nodejs developers. For a few months a I’m trying to find best practice for making extendable and modifiable node (npm) modules.
For better understanding: In most of PHP frameworks (like as Symfony, Laravel, Nette) we have DI container which can be used for changing or adding own implementation for services coming from packages. For example. I have a cart package which implements service for calculating cart price and apply taxes. When i need to change taxes calculation I can change implementation over DI container like as
services:
myTaxCalculator:
class: MyTaxCalculator
Package\Taxes\CalculatorInterface: ‘#myTaxCalculator’
and now when package work with Package\Taxes\CalculatorInterface use my own calculator instead of default implementation.
And I looking for something like this in javascript(typescript)/nodejs. If I build any package and in package I need function for calculate taxes use this const taxCalculator = require(‘...’) but now I can’t change implementation of this function.
Of course I can make package configurable. Add some mechanism for set a custom function for specific cases but I think that I need this logic for all classes / function which is used in application to never have to call require(‘something’).
The point is build basic and standard package with default logic which can be in concrete application modify to solve customer problems without writing a new package with 90% same code.
I know that exists some IoC/DI implementation for javascript(typescript) / nodejs like as InversifyJS but I’m not sure when is a best way for javascript(typescript) / nodejs applications.
Do you have any experiences with this? How do you solve these problems?
Thanks for any response!
I wouldn't say I'm an expert or "best practices guru", but I think three scenarios are pretty common. I won't dig into Inversify because you're already aware of it.
Take an object with config at the entry point class/function. Default to your implementation.
interface TaxCalculator { /* tax related stuff */ }
interface CalculateCartPriceArgs {
taxCalculator: TaxCalculator,
// probably lots of other stuff
}
export function calculateCartPrice({
taxCalculator = defaultTaxCalculator
}: CalculateCartPriceArgs) {
// implementation
}
Plugins / middleware.
Expose internals to allow the user to build his own version of your thing.

How to use multiples Parse instance

Is there a way to initialize multiple parse apps in react javascript, currently i am initializing single parse app like this
Parse.initialize(config.appId);
Parse.serverURL = config.serverURL;
Currently with the implementation of the SDK you cannot do that. Theses methods and properties are static as you can see here
What you can do is to use the REST API
You can also suggest this feature on the GitHub repository

Is it possible to use Graphql generated schema as Flow definitions?

I have a project that uses the convo GraphQL, Relay and Flow. Is there a way to use GraphQL schema to feed Flow so the React props can be typed without redeclaring the types?
For Relay I'm already using the script that generates two files: schema.json and schema.graphql. The Babel plugin uses schema.json to translate the queries into javascript.
The other file, schema.graphql looks similar to Flow syntax definition for types, but there are differences. I've tried once to import type {Definition} from "./schema.graphql" from it but was failing silently.
The problem with that is GraphQL scalar-types can be used to represent values in various formats and they do not inherit from a base type you could fall back to for flow.
Scalar can not only verify a "string" but "string of 32 hexadecimal digits". It's not possible to declare this kind of type in flow.
Here are some alternatives: babel-plugin-typecheck, json-to-flow
So after a while I decided to tackle this since our project started to grow and we started to loosen our types. In the end the simplest solution has been to grab the printerSchema and modify it so it outputs flow friendly text, save it to a .js file and point libraries to there.
I'll try to post it in github in a later date

Categories

Resources