Skip to content

Commit d2a98be

Browse files
committed
Update part8a
1 parent cefe3e2 commit d2a98be

File tree

3 files changed

+177
-51
lines changed

3 files changed

+177
-51
lines changed

src/content/8/en/part8a.md

Lines changed: 92 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -389,19 +389,62 @@ has a resolver which returns <i>all</i> objects from the *persons* array.
389389
```js
390390
() => persons
391391
```
392-
393-
Start the server by running `node index.js` in the terminal.
394392

395393
### Apollo Studio Explorer
396394

397-
When Apollo server is run in development mode the page [http://localhost:4000](http://localhost:4000) has a button <i>Query your server</i> that takes us to [GraphOS Studio Explorer](https://www.apollographql.com/docs/graphos/platform/explorer). This is very useful for a developer, and can be used to make queries to the server.
395+
Let's add the following scripts to <i>package.json</i> to run the application:
396+
397+
```json
398+
{
399+
//...
400+
"scripts": {
401+
"start": "node index.js", // highlight-line
402+
"dev": "node --watch index.js", // highlight-line
403+
// ...
404+
}
405+
}
406+
```
407+
408+
When Apollo server is run in development mode the page [http://localhost:4000](http://localhost:4000) takes us to [GraphOS Studio Explorer](https://www.apollographql.com/docs/graphos/platform/explorer). This is very useful for a developer, and can be used to make queries to the server.
398409

399410
Let's try it out:
400411

401412
![apollo studio Example Query with response allPersons](../../images/8/1x.png)
402413

403414
At the left side Explorer shows the API-documentation that it has automatically generated based on the schema.
404415

416+
### Schema syntax highlighting in VS Code
417+
418+
The schema in our code is defined using template literal syntax:
419+
420+
```js
421+
const typeDefs = `
422+
type Person {
423+
name: String!
424+
phone: String
425+
street: String!
426+
city: String!
427+
id: ID!
428+
}
429+
430+
type Query {
431+
personCount: Int!
432+
allPersons: [Person!]!
433+
findPerson(name: String!): Person
434+
}
435+
`
436+
```
437+
438+
The schema contains structural information, but in the code editor the whole content appears in the same color and automatic formatting tools like Prettier cannot format its contents. We can enable GraphQL schema syntax highlighting and, for example, autocompletion in VS Code by installing the [GraphQL: Language Feature Support](https://marketplace.visualstudio.com/items?itemName=GraphQL.vscode-graphql) extension.
439+
440+
We need to somehow indicate to the extension that _typeDefs_ contains GraphQL. There are several ways to do this. We'll do it now by adding the type-indicating comment _/* GraphQL */_ before the template literal string:
441+
442+
443+
444+
![VS Code uses syntax highlighting for the GraphQL schema when the comment /* GraphQL */ is added before the template literal string](../../images/8/1z.png)
445+
446+
Now the syntax highlighting works. The comment helps the installed extension recognize the string as GraphQL and provide intelligent editor features, but it does not affect the application's runtime. Prettier can now also format the schema.
447+
405448
### Parameters of a resolver
406449

407450
The query fetching a single person
@@ -511,6 +554,32 @@ type Query {
511554

512555
so a person now has a field with the type <i>Address</i>, which contains the street and the city.
513556

557+
Because the objects saved in the array do not have an <i>address</i> field, the default resolver is not sufficient.
558+
Let's add a resolver for the <i>address</i> field of <i>Person</i> type:
559+
560+
```js
561+
const resolvers = {
562+
Query: {
563+
personCount: () => persons.length,
564+
allPersons: () => persons,
565+
findPerson: (root, args) =>
566+
persons.find(p => p.name === args.name)
567+
},
568+
// highlight-start
569+
Person: {
570+
address: (root) => {
571+
return {
572+
street: root.street,
573+
city: root.city
574+
}
575+
}
576+
}
577+
// highlight-end
578+
}
579+
```
580+
581+
So every time a <i>Person</i> object is returned, the fields <i>name</i>, <i>phone</i> and <i>id</i> are returned using their default resolvers, but the field <i>address</i> is formed by using a self-defined resolver. The parameter *root* of the resolver function is the person-object, so the street and the city of the address can be taken from its fields.
582+
514583
The queries requiring the address change into
515584

516585
```js
@@ -560,32 +629,26 @@ The person-objects saved in the server are not exactly the same as the GraphQL t
560629

561630
Contrary to the <i>Person</i> type, the <i>Address</i> type does not have an <i>id</i> field, because they are not saved into their own separate data structure in the server.
562631

563-
Because the objects saved in the array do not have an <i>address</i> field, the default resolver is not sufficient.
564-
Let's add a resolver for the <i>address</i> field of <i>Person</i> type :
632+
Let's modify the resolver for the _address_ field so that it destructures the needed fields from the parameter it receives:
565633

566634
```js
567635
const resolvers = {
568636
Query: {
569637
personCount: () => persons.length,
570638
allPersons: () => persons,
571-
findPerson: (root, args) =>
572-
persons.find(p => p.name === args.name)
639+
findPerson: (root, args) => persons.find((p) => p.name === args.name),
573640
},
574-
// highlight-start
575641
Person: {
576-
address: (root) => {
577-
return {
578-
street: root.street,
579-
city: root.city
642+
address: ({ street, city }) => { // highlight-line
643+
return {
644+
street, // highlight-line
645+
city, // highlight-line
580646
}
581-
}
582-
}
583-
// highlight-end
647+
},
648+
},
584649
}
585650
```
586651

587-
So every time a <i>Person</i> object is returned, the fields <i>name</i>, <i>phone</i> and <i>id</i> are returned using their default resolvers, but the field <i>address</i> is formed by using a self-defined resolver. The parameter *root* of the resolver function is the person-object, so the street and the city of the address can be taken from its fields.
588-
589652
The current code of the application can be found on [Github](https://github.com/fullstack-hy2020/graphql-phonebook-backend/tree/part8-1), branch <i>part8-1</i>.
590653

591654
### Mutations
@@ -610,20 +673,29 @@ The Mutation is given the details of the person as parameters. The parameter <i>
610673
Mutations also require a resolver:
611674

612675
```js
613-
const { v1: uuid } = require('uuid')
676+
const { v1: uuid } = require('uuid') // highlight-line
614677

615678
// ...
616679

617680
const resolvers = {
618-
// ...
681+
Query: {
682+
// ...
683+
},
684+
Person: {
685+
// ...
686+
},
687+
// highlight-start
619688
Mutation: {
620689
addPerson: (root, args) => {
621690
const person = { ...args, id: uuid() }
622691
persons = persons.concat(person)
623692
return person
624693
}
625694
}
695+
// highlight-end
626696
}
697+
698+
// ...
627699
```
628700

629701
The mutation adds the object given to it as a parameter *args* to the array *persons*, and returns the object it added to the array.
@@ -642,7 +714,7 @@ mutation {
642714
) {
643715
name
644716
phone
645-
address{
717+
address {
646718
city
647719
street
648720
}

src/content/8/fi/osa8a.md

Lines changed: 85 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ Kuten huomaamme, GraphQL-kyselyn ja siihen vastauksena tulevan JSON:in muodoilla
236236

237237
GraphQL:n skeema kuvaa ainoastaan palvelimen ja sitä käyttävien clientien välillä liikkuvan tiedon muodon. Tieto voi olla organisoituna ja talletettuna palvelimeen ihan missä muodossa tahansa.
238238

239-
Nimestään huolimatta GraphQL:llä ei itse asiassa ole mitään tekemistä tietokantojen kanssa, se ei ota mitään kantaa siihen miten data on tallennettu. GraphQL-periaattella toimivan API:n käyttämä data voi siis olla talletettu relaatiotietokantaan, dokumenttitietokantaan tai muille palvelimille, joita GraphQL-palvelin käyttää vaikkapa REST:in välityksellä.
239+
Nimestään huolimatta GraphQL:llä ei itse asiassa ole mitään tekemistä tietokantojen kanssa, se ei ota mitään kantaa siihen miten data on tallennettu. GraphQL-periaatteella toimivan API:n käyttämä data voi siis olla talletettu relaatiotietokantaan, dokumenttitietokantaan tai muille palvelimille, joita GraphQL-palvelin käyttää vaikkapa REST:in välityksellä.
240240

241241
### Apollo Server
242242

@@ -248,7 +248,7 @@ Luodaan uusi npm-projekti komennolla _npm init_ ja asennetaan tarvittavat riippu
248248
npm install @apollo/server graphql
249249
```
250250

251-
Alustava toteutus on seuraavassa
251+
Alustava toteutus kirjoitettuna tiedostoon <i>index.js</i> on seuraavassa
252252

253253
```js
254254
const { ApolloServer } = require('@apollo/server')
@@ -386,14 +386,59 @@ resolveri on funktio, joka palauttaa <i>kaikki</i> taulukon _persons_ oliot
386386

387387
### Apollo Studio Explorer
388388

389-
Kun Apollo-serveriä suoritetaan sovelluskehitysmoodissa, ja mennään sivulle [http://localhost:4000](http://localhost:4000) päästään nappia <i>Query your server</i> painamalla sovelluskehittäjälle erittäin hyödyllisen [Apollo Studio Explorer](https://www.apollographql.com/docs/studio/explorer/explorer/)-näkymän, joka avulla on mahdollista tehdä kyselyjä palvelimelle.
389+
Lisätään tiedostoon <i>package.json</i> skriptit sovelluksen suoritusta varten:
390+
391+
```json
392+
{
393+
//...
394+
"scripts": {
395+
"start": "node index.js", // highlight-line
396+
"dev": "node --watch index.js", // highlight-line
397+
// ...
398+
}
399+
}
400+
```
401+
402+
Kun Apollo-serveriä suoritetaan sovelluskehitysmoodissa ja mennään sivulle [http://localhost:4000](http://localhost:4000), päästään sovelluskehittäjälle erittäin hyödylliseen [Apollo Studio Explorer](https://www.apollographql.com/docs/studio/explorer/explorer/)-näkymään, jonka avulla on mahdollista tehdä kyselyjä palvelimelle.
390403

391404
Kokeillaan
392405

393406
![](../../images/8/1x.png)
394407

395408
Vasemmassa laidassa Explorer näyttää mukavasti myös automaattisesti skeeman perusteella muodosteutun API-dokumentaation.
396409

410+
### Skeeman syntaksikorostus VS Codessa
411+
412+
Skeema on määritelty koodissamme template literal -syntaksin avulla:
413+
414+
```js
415+
const typeDefs = `
416+
type Person {
417+
name: String!
418+
phone: String
419+
street: String!
420+
city: String!
421+
id: ID!
422+
}
423+
424+
type Query {
425+
personCount: Int!
426+
allPersons: [Person!]!
427+
findPerson(name: String!): Person
428+
}
429+
`
430+
```
431+
432+
Skeema sisältää rakenteellista tietoa, mutta koodieditorissa koko sisältö näkyy samanvärisenä, eivätkä esimerkiksi automaattiset muotoilutyökalut kuten Prettier osaa muotoilla sen sisältöä. Saamme VS Codeen GraphQL-skeeman syntaksikorostuksen ja esimerkiksi automaattisen täydennyksen käyttöön asentamalla [GraphQL: Language Feature Support](https://marketplace.visualstudio.com/items?itemName=GraphQL.vscode-graphql) -lisäosan.
433+
434+
Lisäosalle pitää vielä jotenkin ilmaista, että _typeDefs_ sisältää GraphQL:ää. Tähän on useita tapoja. Tehdään se nyt lisäämällä template literal -merkkijonon eteen tyypin määrittävä kommentti _/* GraphQL */_:
435+
436+
437+
438+
![VS Code käyttää syntaksikorostusta GraphQL-skeemaan, kun template literal -merkkijonon eteen on lisätty kommentti /* GraphQL */](../../images/8/1z.png)
439+
440+
Nyt syntaksikorostus toimii. Kommentti auttaa asentamaamme lisäosaa tunnistamaan merkkijonon GraphQL:ksi ja tarjoamaan älykkäitä ominaisuuksia editorissa, mutta ei vaikuta itse sovelluksen suoritukseen. Myös Prettier osaa nyt muotoilla skeemaa.
441+
397442
### Resolverin parametrit
398443

399444
Yksittäisen henkilön hakevan kyselyn
@@ -500,6 +545,31 @@ type Query {
500545

501546
eli henkilöllä on nyt kenttä, jonka tyyppi on <i>Address</i>, joka koostuu kadusta ja kaupungista.
502547

548+
Koska taulukkoon talletetuilla olioilla ei ole kenttää <i>address</i>, oletusarvoinen resolveri ei enää riitä. Lisätään resolveri tyypin <i>Person</i> kentälle <i>address</i>:
549+
550+
```js
551+
const resolvers = {
552+
Query: {
553+
personCount: () => persons.length,
554+
allPersons: () => persons,
555+
findPerson: (root, args) =>
556+
persons.find(p => p.name === args.name)
557+
},
558+
// highlight-start
559+
Person: {
560+
address: (root) => {
561+
return {
562+
street: root.street,
563+
city: root.city
564+
}
565+
}
566+
}
567+
// highlight-end
568+
}
569+
```
570+
571+
Eli aina palautettaessa <i>Person</i>-oliota, palautetaan niiden kentät <i>name</i>, <i>phone</i> sekä <i>id</i> käyttäen oletusarvoista resolveria, kenttä <i>address</i> muodostetaan itse määritellyn resolverin avulla. Resolverifunktion parametrina _root_ on käsittelyssä oleva henkilö-olio, eli osoitteen katu ja kaupunki saadaan sen kentistä.
572+
503573
Osoitetta tarvitsevat kyselyt muuttuvat muotoon
504574

505575
```js
@@ -549,31 +619,6 @@ Nyt siis palvelimen tallettamat henkilö-oliot eivät ole muodoltaan täysin sam
549619

550620
Toisin kuin tyypille <i>Person</i> ei tyypille <i>Address</i> ole määritelty <i>id</i>-kenttää, sillä osoitteita ei ole talletettu palvelimella omaan tietorakenteeseensa.
551621

552-
Koska taulukkoon talletetuilla olioilla ei ole kenttää <i>address</i> oletusarvoinen resolveri ei enää riitä. Lisätään resolveri tyypin <i>Person</i> kentälle <i>address</i>:
553-
554-
```js
555-
const resolvers = {
556-
Query: {
557-
personCount: () => persons.length,
558-
allPersons: () => persons,
559-
findPerson: (root, args) =>
560-
persons.find(p => p.name === args.name)
561-
},
562-
// highlight-start
563-
Person: {
564-
address: (root) => {
565-
return {
566-
street: root.street,
567-
city: root.city
568-
}
569-
}
570-
}
571-
// highlight-end
572-
}
573-
```
574-
575-
Eli aina palautettaessa <i>Person</i>-oliota, palautetaan niiden kentät <i>name</i>, <i>phone</i> sekä <i>id</i> käyttäen oletusarvoista resolveria, kenttä <i>address</i> muodostetaan itse määritellyn resolverin avulla. Resolverifunktion parametrina _root_ on käsittelyssä oleva henkilö-olio, eli osoitteen katu ja kaupunki saadaan sen kentistä.
576-
577622
Muutetaan kentän _address_ resolveria vielä siten, että se destrukturoi tarvitsemansa kentät saamastaan parametrista:
578623

579624
```js
@@ -618,20 +663,29 @@ Mutaatio siis saa parametreina käyttäjän tiedot. Parametreista <i>phone</i> o
618663
Myös mutaatioita varten on määriteltävä resolveri:
619664

620665
```js
621-
const { v1: uuid } = require('uuid')
666+
const { v1: uuid } = require('uuid') // highlight-line
622667

623668
// ...
624669

625670
const resolvers = {
626-
// ...
671+
Query: {
672+
// ...
673+
},
674+
Person: {
675+
// ...
676+
},
677+
// highlight-start
627678
Mutation: {
628679
addPerson: (root, args) => {
629680
const person = { ...args, id: uuid() }
630681
persons = persons.concat(person)
631682
return person
632683
}
633684
}
685+
// highlight-end
634686
}
687+
688+
// ...
635689
```
636690

637691
Mutaatio siis lisää parametreina _args_ saamansa olion taulukkoon _persons_ ja palauttaa lisätyn olion.
@@ -650,7 +704,7 @@ mutation {
650704
) {
651705
name
652706
phone
653-
address{
707+
address {
654708
city
655709
street
656710
}

src/content/images/8/1z.png

31.3 KB
Loading

0 commit comments

Comments
 (0)