Advanced
Web Applications


GraphQL

GraphQL Endpoint

We can use GraphQL endpoint directly or via user-interface like GraphiQL. NKOD GraphQL API is a reasonable example.

GraphQL Schema

  • Basic example
  • Types
  • Required (!)

type Query {
  users: [User]
}

type User {
  id: ID!
  name: String
}
    

GraphQL Schema

  • Arguments

type Query {
  users: [User]
  user(identifier: String): User
  groups: [Group]
}

type User {
  id: ID
  name: String
}

type Group {
  id: ID
  users: [User]
  homepage: String
}
  

Assignment: GraphQL (1/5)

./practical-08/graphql

Employ express, graphql, graphql-http, and ruru (GraphQL client), libraries to implement GraphQL endpoint. Follow the steps on this and following slides to complete the assignment.

Start from a simple GraphQL Server with Express. Just install the libraries, copy (and read) the source code into an file and start the file using node command.

Assignment: GraphQL (2/5)

Next use GraphQLSchema to implement schema (bellow), create your own test data. See GraphQL.js page for example of using GraphQLSchema. Notice the resolve function.

Mind CommonJS (require) and ES Modules (import ... from "") style of imports. You can use .mjs extension for ESModule import and .cjs extension for CommonJS type of imports.


type Query {
  users: [User]
}

type User {
  id: ID!
  name: String
}
    

Note: Use GraphQLList to represent a list of types.

Assignment: GraphQL (3/5)

Make sure you understand all the concepts before you continue.

Update the previous schema, add `user`. See second example at Constructing Types for information on how to work with arguments.


type Query {
  users: [User]
  user(identifier: String): User
}

type User {
  id: ID
  name: String
}
  

Assignment: GraphQL (4/5)

Update the previous schema, add `groups`.

You may notice that we share the user object in here. It would be great (performance) not to construct the whole group object but to re-use some functionality. A solution is to declare and reuse multiple resolve functions. In fact, you can declare a resolve function in every object with type. The first argument of a resolve function is source object, i.e. parent.

Add a resolve function to Group.users and use the parent argument to get list of all users.


type Query {
  users: [User]
  user(identifier: String): User
  groups: [Group]
}

type User {
  id: ID
  name: String
}

type Group {
  id: ID
  users: [User]
  homepage: String
}
  

Assignment: GraphQL (5/5)

We should not put business logic or model into the resolve functions (remember MVC)? Extract the functionality into another layer.

Introduce a service/object UserService, with methods (TypeScript-like notation):

  • getUsers(): Promise<{ id: string, name: string }> - return all users as objects
  • getUsersIdentifiers() : Promise<string[]> - return identifiers of all users
  • getUser(identifier:string): Promise< { id: string, name: string}> - return data for user with given identifier.

In a similar manner introduce and user GroupService:

  • getGroups() : Promise<{id:string, homepage: string, users: string[]}> - return all groups as objects. Users are represented using identifiers.

This is the end of the first assignment.

Assignment: GraphQL HTTP

./practical-08/http

Expand implementation from previous assignment by fetching the data from an HTTP endpoint.

Unfortunately there is no OpenAPI specification for the endpoints :(

Assignment: GraphQL MySQL

./practical-08/mysql

Employ mysql (documentation) package to fetch data from a MySQL server with following schema.


CREATE TABLE `users` (
  `id` int NOT NULL,
  `name` varchar(256) NOT NULL
);

CREATE TABLE `groups` (
  `id` int NOT NULL,
  `homepage` varchar(256) NOT NULL
);

CREATE TABLE `membership` (
  `user_id` int NOT NULL,
  `group_id` int NOT NULL
);
    

Assignment: GraphQL MySQL

You can use database at webik.

  • user: 'public'
  • database: 'public'
  • password: '*****'

You can proxy MySQL port from webik to your localhost.


  ssh webik -L 3306:localhost:3306
    

Assignments

Make sure your code is of reasonable quality and follow best practices.


You must implement and submit the assignments before 10.5.2024 23:59 UTC.

Additional resources

Questions, ideas, or any other feedback?

Please feel free to use the anonymous feedback form.