GraphQL pt 2

Motivation

Now we’d like to write a data scheme and let Apollo generate the Angular Code for us [1]

Drafting

No matter from which direction we are coming (backend first, frontend first, any mocking server), we’d need a GraphQL Scheme. There are several specialized GraphQL IDEs, coming from [2], let’s try this sandbox https://graphql.org/swapi-graphql together with a cheat sheet [3].

Remeber, we wanted to write kind of a Todo App, now we have to roll-out a central data model of it. Remember also, we wanted to start simple.

After 30mins of chilling I came up with an idea: we got articles, they have tags, an article contains certain types of paragraphs, say text, forumlas and snippets – any of them encoded as string. We’d like to do typical CRUD operations on any of them.

We might also want to install the vs-code graphql extension: https://www.apollographql.com/docs/devtools/editor-plugins/

After looking some samples and get into the scheme description [4], I created the following definition, where the Type Query defines read operations and the type Mutation defines writes. Store this file in the top directory of your project as:

schema.graphql

enum ParagraphType {
  PlainText,
  Snippet,
  Formula
}

"This is a tag"
type Tag {
  name : String
}

"This is a paragraph"
type Paragraph {
  id: String!
  type: ParagraphType!
  content: String!
}

"This is a section"
type Section {
  id: String!
  name: String
  tags: [Tag!]
  subsections: [Section!]
  paragraphs: [Paragraph!]
}

type Query {
  getSections: [Section]
  getTags: [Tag]
}

type Mutation {
  addSection(sectionId: String!, name: String!) : Section
  addParagraph(sectionId: String!, type: ParagraphType!, content: String!) : Paragraph
  addTag(sectionId: String!, name : String!) : Tag

  removeSection(sectionId : String!) : Section
  removeParagraph(paragaphId : String!) : Paragraph
  removeTag(name : String!) : Tag
}

schema {
  query : Query
  mutation : Mutation
}

Code generation

  • Now we are in the position to create TypeScript types
  • This shows, how we’d like to generate our code: https://graphql-code-generator.com/ we’ll follow the getting-started setup
  • npm install -g @graphql-codegen/cli
    (I had to downgrade an „is-promise“ package there from 2..2.0 to 2.1.0, to get it work)
  • call graphql-codegen init
  • Ideally we get a menu now, select „Application with Angular“, type „../schema.graphql“, output to „src/app/generated/graphql.ts“, no introspection file, and „codegen“ for the script name
  • Now run npm install and npm run codegen
  • We observe: „Unable to find any GraphQL type definitions“ whoopsie.
  • Let’s create a file called queries.graphql anywhere below src, we choose the directory „src/app/main-page“ here
query listSections {
  getSections {
    id
    name
  }
}
  • npm run codegen again
  • we got a new file src/app/generated/graphql.ts – have a look
  • to avoid committing this via git, add the line /src/app/generated to .gitignore file – because we won’t commit generated files
  • now we want to consume this:

main-page.component.ts

import { Component, OnInit } from '@angular/core';
import { Observable } from 'rxjs';
import { flatMap } from 'rxjs/operators';
import { Section, ListSectionsGQL } from '../generated/graphql';

@Component({
  selector: 'app-main-page',
  templateUrl: './main-page.component.html',
  styleUrls: ['./main-page.component.scss'],
})
export class MainPageComponent implements OnInit {
  sections: Observable<Section>;

  // Dependency Injection of GQL
  constructor(private gql: ListSectionsGQL) {}

  ngOnInit() {
    this.sections = this.gql
      .watch()
      .valueChanges.pipe(flatMap((result) => result.data.getSections));
  }
}

main-page.component.html

<div class="container">
<h2>Rates</h2>
<ul class="list-group">
  <li *ngFor="let section of sections | async" class="list-group-item">
    {{section.name}}
  </li>
</ul>
</div>

Observations

  • compile & run
  • we used dependency injection to retrieve a type safe result for now
  • the result list is empty – well, we actually do not have a server, producing this data yet
  • the network calls would be a first candidate for refactoring / introducing an architecture, which „binds“ query and ui more directly
  • perform a git commit

References


Beitrag veröffentlicht

in

von

Schlagwörter: