GraphQL adventures. Вводный курс молодого бойца по созданию GraphQL прокси сервера с использованием typescript. Опыт миграции legacy API services на GraphQL и сложности, возникающие при этом.
2. 2BREST
ILYA LABACHEUSKI
Software developer in EPAM systems.
Also a member of the IT Shark Community.
The main field is frontend Javascript development. I have some experience in
Node.js and React Native. Some other fields of interest are CAD systems, simple
engineering and some bad habits. :)
ILYA
LABACHEUSKI
EPAM Systems, software developer
4. 4BREST
GraphQL. What is it?
A query language for your API
Ask for what you need, get exactly that!
{
hero {
aliasName: name
height
mass
}
}
{
"hero": {
"aliasName": "Luke Skywalker",
"height": 1.72,
"mass": 77
}
}
5. 5BREST
This presentation
1. A very simple tutorial for setting up a GraphQL server
written in TypeScript.
2. Some adventures and thoughts about migration to
GraphQL from REST API.
18. 18BREST
Type it (with TypeScript)
const airportName = (props: Props) => (
<div>Name: {props.graphqlValue.airport.fullName}</div>
)
export default connectGraphQL<Props, AirportNameQuery,
AirportNameInput>(DeviceNameComponent, () => ({
query: ...
variables: {
airportId: 123342334
},
}))
No fullName in type QueryResult
No airportId in type AirportNameInput
19. 19BREST
• Safety — static verification at compile time
• Editor tooling — code help, highlighting, going to definition
• One source of truth — types should have unique reference
Advantages
21. 21BREST
Good tools to use
• ts-node — the same as node for TypeScript
• tslint + rules — eslint for TypeScript
• express (koa …) — works well with TypeScript
• apollo-server-express — for GraphQL
• graphql-playground-middleware-express — a playground
• graphql-voyager — to see everything graphically
• jest + ts-jest — unit testing
• nodemon — reloading the server
• graphql-import — write in .graphql files
32. 32BREST
Schemifying your REST APIs
• Write by hand?
• Auto generate?
• Do both?
• Do you have full documentation for REST APIs?
• Are all fields in requests and responses defined?
33. 33BREST
Writing a schema manually
Pros:
• GraphQL will be defined for your specific needs.
• Easy to extend, simplify or remove types.
Cons:
• Any update in REST APIs requires attention.
• Requires big analysis of how you use your API.
• The process is long.
34. 34BREST
Auto generation from REST APIs
Pros:
• You can generate a schema from existing REST schemas
(Swagger/OpenAPI) relatively easily.
• You can combine multiple API REST and GraphQL services.
Cons:
• The schema will be more complex.
• Changes in types require a complex tool to generate an updated
schema properly.
35. 35BREST
Combination of both
Pros:
• Automatic translation for basic types.
• Flexibility to make your schema simpler and better.
Cons:
• Your schema will be the source of truth and will not repeat your
REST APIs.
• Still a lot of work.
36. 36BREST
No documentation for REST APIs
What we have done:
- Logged all API requests and their responses to JSON.
- Translated responses in JSON files to TypeScript types.
- Translated TypeScript types to a GraphQL schema.
- Tried to make an automatic script that will repeat all the needed
API calls to make a ‘happy flow.’
49. 49BREST
Mimicing REST API vs making GraphQL first
query {
flightResourse {
getPassengers(flightId: ID!) : Passengers
}
}
# vs
query {
getPassengersByFlightId(flightId: ID!) : Passengers
}
Nested structure
Flat structure with many root queries
50. 50BREST
Mimicing REST API
type MutationOnPage {
postPassengers(opts: PassengersInput!): PassengersResponseSubmit
}
Can be a completely unique type.
51. 51BREST
Mimicing REST API: getting your data
type MutationOnPage {
postPassengers(opts: PassengersInput!): PassengersResponseSubmit
}
input PassengersInput {
baggage: [Baggages!]!
Person: Person!
}
input BaggagesInput {
Items: [Baggage!]!
}
Comes from another request, that depends on
another request, that depends… and so one
52. 52BREST
Mimicing REST API forces to make a nested schema
query getInfoForPassengersInput {
getFlight(id: ID!) {
getPassengers {
getBaggage {
...
}}}}
query getInfoForInsuranceInput {
getFlight(id: ID!) {
getServices {
getPassengers {
...
}}}}
For every unique situation you will have its
own nesting with possibly unique types
53. 53BREST
Mimicing REST APIs
Pros:
• Easy to convert
Cons:
• Your schema will be a mess of unique flows and types.
• Getting data is a traversing graph.
57. 57BREST
REST APIs with expiration tokens
`https://api.oursite.com/{token}`
query {
flight(id: ID!) { <- 300 ms REST API call
passengers { <- 400 ms REST API call
baggage { <-- here the token expires
}
}
}
}
You should have a strategy what to do in such case.
58. 58BREST
Query complexity
query {
flight(id: ID!) {
carrier
price
}
airport(limit: 20) {
name
city
}
}
flight + carrier + price = 3
In case for every airport is needed separate
REST API request:
(airport + name + city) * 20 = 60
Total = 63